2014年9月20日土曜日

上場しているすべての会社の株価をすべて取得するプログラムを作る

これまでのところでは1会社分の1日分のデータを取得するプログラム
http://mosirobo.blogspot.jp/2014/09/javahtml.html
http://mosirobo.blogspot.jp/2014/09/javacsv.html
http://mosirobo.blogspot.jp/2014/09/javahtml_4.html

と、1会社の過去の株価すべてを取得するプログラムの2つを作成しました。
http://mosirobo.blogspot.jp/2014/09/blog-post.html
http://mosirobo.blogspot.jp/2014/09/html.html
http://mosirobo.blogspot.jp/2014/09/csv.html
データを解析し、株ロボットを作るにはなるべく多くの会社の株価がほしいのですが、
全て手作業でやっていては非常に面倒です。
ですのでループを回して、すべての証券コードを入力していこうと思います。

まず最初に、プログラムを表示します
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class getURL6 {
	public String getURL6(int ccode, String eyyyymmdd, String syyyymmdd) {
		String aa = "";
		String syyyy = syyyymmdd.substring(0, 4);	//20140914前から4文字
		String smm = syyyymmdd.substring(5, 6);		//前から5.6文字
		String sdd = syyyymmdd.substring(7, 8);		//前から7,8文字
		String eyyyy = eyyyymmdd.substring(0, 4);
		String emm = eyyyymmdd.substring(5, 6);
		String edd = eyyyymmdd.substring(7, 8);
		int page = 1;
    
		String reqUrl = "http://info.finance.yahoo.co.jp/history/?code="+ccode+".T&sy="+syyyy+"&sm="+smm+"&sd="+sdd+"&ey="+eyyyy+"&em="+emm+"&ed="+edd+"&tm=d&p=";
		
		String regex ="【(.*)】:";	//改行以外のすべての文字
		String regex2 = "~([0-9]{2,})件/([0-9]{2,})件中</span>";
		String regex3 = "<td class=\"stoksPrice\">(.*?)</td>";

		while(true){		//ページ数を繰り返す
		try {
			String url = reqUrl + page;
			String bb ="";
			bb = getSourceText(new URL(url));

			//証券コードがエラーの場合は終了
			Pattern p = Pattern.compile(regex);
			Matcher m1 = p.matcher(bb);
			String cc ="aaa";
			if(m1.find()){
				cc = m1.group(1);
				//System.out.println(cc);
			}
			if(cc.equals("")){
				//System.out.println("break");
				break;
			}
			//上場終了していたら終了
			//<td class="stoksPrice">---</td>
			Pattern p3 = Pattern.compile(regex3);
			Matcher m3 = p3.matcher(bb);
			String ff = "fff";
			if(m3.find()){
				ff = m3.group(1);
			}
			if(ff.equals("---")){
				//System.out.println("break");
				break;
			}

			//ページが足りなくなったら終了
			//<span class="stocksHistoryPageing yjS">4301~4328件/4328件中</span>を利用後ろ2つの数字が同じならbreak
			Pattern p2 = Pattern.compile(regex2);
			Matcher m2 = p2.matcher(bb);
			String dd = "aaa";
			String ee = "bbb";
			if(m2.find()){
				dd = m2.group(1);
				ee = m2.group(2);
				//System.out.println(dd);
				//System.out.println(ee);
			}
			//先に読み込んでから消す
			aa = aa+bb;
			if(dd.equals(ee)){
				break;
			}
			page = page+1;
			//一秒停止
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO 自動生成された catch ブロック
				e.printStackTrace();
			}
		} catch (MalformedURLException e) {
			// TODO 自動生成された catch ブロック
			e.printStackTrace();
		} catch (IOException e) {
			// TODO 自動生成された catch ブロック
			e.printStackTrace();
		}
		}
		return aa;


    }
	public static String getSourceText(URL url) throws IOException {
		InputStream in = url.openStream();	//接続

		//文字エンコーディング
		InputStreamReader isr = new InputStreamReader(in, "UTF-8");

		StringBuilder sb = new StringBuilder();

		try {
		BufferedReader bf = new BufferedReader(new InputStreamReader(in));
		String s;
		while ((s=bf.readLine())!=null) {
		sb.append(s);
		}
		} finally {
		in.close();
		}
		return sb.toString();
		}

}

以前のものとの違いは、
過去データの量はは上場企業によってことなるため、最後のデータまで辿り着いたら終了するようにしました。
データが最後になったという判定は、表示件数の部分を正規表現で抜き出し、
表示件数が総データ数と同じになった場合に終了します。
また、エラー処理として、証券コード該当する会社がない場合と、上場終了していた場合にエラーがでたので例外処理を入れていきます。
また、過度なアクセスはサーバー側の負荷になり、サーバーエラーを返されるので、
1ページ読み込んだら1秒待つようなプログラムを入れました。

0 件のコメント:

コメントを投稿