PythonでYahooファイナンスの時系列データを取得してみた
第7章のデータダウンロードについて。
まずはlibフォルダのstock_data_getter.py
#!/usr/bin/env python # -*- coding: utf-8 -*- import codecs, os import datetime import urllib.request, urllib.error import re # Yahoo!ファイナンスから株価データをダウンロードするクラス class StockDataGetter: def __init__(self, frm, to, market): self.from_date = datetime.datetime.strptime(frm, '%Y/%m/%d') self.to_date = datetime.datetime.strptime(to, '%Y/%m/%d') self.market = market self.data_dir = 'data' # 株価データの新規取得 def get_price_data(self, code): self.code = code self.save_to_file(self.prices_text()) def update_price_data(self, code): self.code = code if os.path.exists(self.data_file_name()): self.get_from_date() self.append_to_file(self.prices_text()) else: self.save_to_file(self.prices_text()) # ファイルに記録される文字列 def prices_text(self): prices = self.get_price_data_from_historical_data_pages() if len(prices) == 0: return [] else: return self.prices_to_text(prices) # 時系列データのページを読み込む def get_price_data_from_historical_data_pages(self): page_num = 1 prices = [] reg_data = re.compile(self.reg_prices()) reg_next = re.compile(r'次へ</a></ul>') while True: url = self.url_for_historical_data(page_num) try: request = urllib.request.Request(url) text = urllib.request.urlopen(request).read().decode('utf-8') except urllib.error.HTTPError: return [] except urllib.error.URLError: return [] prices.extend(reg_data.findall(text)) page_num += 1 if reg_next.search(text) == None: break return prices # 時系列データのURL def url_for_historical_data(self, page_num): return 'http://info.finance.yahoo.co.jp/history/?code={0}.{1}&sy={2}&sm={3}&sd={4}&ey={5}&em={6}&ed={7}&tm=d&p={8}'.format(self.code, self.market, self.from_date.year, self.from_date.month, self.from_date.day, self.to_date.year, self.to_date.month, self.to_date.day, page_num) # 株価データ表から株価データを取り出すための # 正規表現パターン def reg_prices(self): return r'<td>(\d{4}年\d{1,2}月\d{1,2}日)</td><td>((?:\d|,)+)</td><td>((?:\d|,)+)</td><td>((?:\d|,)+)</td><td>((?:\d|,)+)</td><td>((?:\d|,)+)</td><td>((?:\d|,)+)</td>' # 株価データの配列を文字列に変換 def prices_to_text(self, prices): new_prices = [] reg_month = re.compile('/(\d)/') reg_day = re.compile('/(\d)$') for price in reversed(prices): p = [] # price[0]は日付 # 年月日の文字を取り除き"/"で区切る p.append(re.sub('[年月]', '/', price[0])) p[0] = re.sub('日', '', p[0]) # 1桁の月や日を0で始まる二桁の数字に if reg_month.search(p[0]): p[0] = reg_month.sub('/0' + reg_month.search(p[0]).group(1) +'/', p[0]) if reg_day.search(p[0]) != None: p[0] = reg_day.sub('/0' + reg_day.search(p[0]).group(1), p[0]) # price[1..6]は値段と出来高 # 数字の間にあるカンマを取り除く for i in range(1, 7): p.append(re.sub(',', '', price[i])) new_prices.append(','.join(p)) return '\n'.join(new_prices) def data_file_name(self): return '{0}/{1}.txt'.format(self.data_dir, self.code) # ファイル中の最終日の翌日を新しい開始日とする def get_from_date(self): last_date = codecs.open(self.data_file_name(), 'r', 'utf-8').readlines()[-1][:10] self.from_date = datetime.datetime.strptime(last_date, '%Y/%m/%d') + datetime.timedelta(days=+1) # データをテキストに保存 def save_to_file(self, prices_text): self.save(prices_text, "w") # 既存のファイルにデータを追加 def append_to_file(self, prices_text): self.save(prices_text, "a") def save(self, prices_text, open_mode): if len(prices_text) != 0: f = codecs.open(self.data_file_name(), open_mode) f.write(prices_text) f.close() print(self.code)
fromが予約語だったのでfrmに変えた。
それからcheckフォルダのget_price_data.py
#!/usr/bin/env python # -*- coding: utf-8 -*- from lib.stock_data_getter import StockDataGetter # 東証銘柄をダウンロードする # 名証銘柄をダウンロードしたければ、market =:n とする # 福証なら market = f、札証なら market = s frm = "2011/01/4" to = "2011/07/30" market = 't' sdg = StockDataGetter(frm, to, market) for code in range(1301, 10000, 1): sdg.get_price_data(code) input()
Googleで'Python ヤフーファイナンス 時系列'などと検索して、
他の方の書いたコードを見ていたらほとんどbeautifulsoupを使っていた。
それほど便利ということだろうから、
10章以降のシミュレーション編に移る前にbeautifulsoupの使い方も覚えることにした。
それなりにPythonが分かってきた。
やっぱり興味ある分野でコード書かないと脳が覚えようとしない。
とりあえず8章に続く。