#この記事について
Pythonとlxmlを使って、webスクレイピングでYahoo!ファイナンスから投資信託の基準価格を取得する方法を解説します。
[追記] Yahoo!ファイナンスからのデータスクレイピングは規約上禁止されているようなので、代わりの方法を利用ください。
Pythonでスクレイピング - 投信協会webから投資信託の基準価格を取得する
##環境
Windows10 x64
Python 2.7.11
lxml 3.5.0
##変更履歴
2016/1/16
- lxml.html.parse()にurlを直接渡すようにした。urllib2のimportを無くした。
- url生成の際に引数をdictに取ってからformat()で展開するようにした。
- forの回し方を変更
- ElementTreeからXPathで取得した要素に.encode('utf-8')する処理をあらかじめmap()でやっておくことにした
#手順
##取得したいデータの位置を確かめる
webスクレイピングではHTML/XML中の特定の位置にあるテキストを抽出するのが目的となるため、まず対象のデータ位置を確認します。この際、Chromeの検証機能が使いやすいです。(以下参照)
Chromeデベロッパー・ツール(要素を検証)の基礎的な使い方
ページを右クリックして「検証」を選択します。(Ctrl+Shift+Iでもよい)
すると画面右半分にHTML要素が現れ、タグを選択すると画面上の対応する部分が反転します。これを使って取得したいデータを特定できるところまで掘り下げていきます。
なおYahoo!ファイナンスの場合は以下の様な階層となっています。
`
ここに基準価格とか
`
##取得したいデータ位置をXPathで書く
XPathとはHTML/XML文書中の任意のコンテンツの位置を表すためのフォーマットです。Chromeでは右クリック -> Copy -> Copy Xpath
でXPathが取得できます。(以下参照)
Chromeだけで任意のノードのXPathを簡単に取得 たぶん革命
今回はid=mainのdiv要素以下にあるテーブルのtd要素がすべてほしいので以下のようにしました。
//*[@id="main"]/div/table//td
##parser()でHTMLを取得し、XPathで必要な要素を抽出する
ここからはPythonで行います。urlをlxml.html.parser()に渡してHTML_Elementsを取得し、そこからXPathで指定した要素を抽出します。最後に型式を整えて[日付, 基準価格, 純資産総額]型式のリストで出力します。日付は最後にyyyymmdd型式の文字列としました。
getNAV.py
# -*- coding: utf-8 -*-
# python 2.7
import lxml.html
import datetime
def getNAV(fundcode, sy, sm, sd, ey, em, ed):
# 引数をdictに突っ込む
d = dict(fundcode=fundcode, sy=sy, sm=sm, sd=sd, ey=ey, em=em, ed=ed)
# dictをアンパックしてURL生成
url = 'http://info.finance.yahoo.co.jp/history/?code={fundcode} \
&sy={sy}&sm={sm}&sd={sd}&ey={ey}&em={em}&ed={ed}&tm=d'.format(**d)
# ElementTreeを取得
tree = lxml.html.parse(url)
# 日付, 基準価額, 純資産の要素をすべて取得しつつ、mapを適用してutf-8化とカンマ除去
contents = map(lambda html: html.text.encode('utf-8').replace(',',''), tree.xpath('//*[@id="main"]/div/table//td'))
# ひとつのリストになっているので[[date, price, cap], [date, price, cap], ...]と分ける
res = []
for i in range(0, len(contents)-1, 3):
date = datetime.datetime.strptime(contents[i], '%Y年%m月%d日').strftime('%Y%m%d')
price = int(contents[i+1])
cap = int(contents[i+2])
res.append([date, price, cap])
return res
if __name__ == '__main__':
# dictにパラメータを突っ込む
args = dict(fundcode='64311104', sy='2015', sm='12', sd='1', ey='2015', em='12', ed='20')
# dictごと渡してアンパック
print getNAV(**args)
参考にした記事
lxml - Processing XML and HTML with Python
lxmlでスクレイピングするときのコツ
[Python] lxmlでスクレイピングのメモ
|