LoginSignup
75
83

More than 5 years have passed since last update.

Pythonでスクレイピング - Yahoo!ファイナンスから投資信託の基準価格を取得する

Last updated at Posted at 2016-01-15

この記事について

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!ファイナンスの場合は以下の様な階層となっています。

<html>
<body>
<div id="wrapper">
<div id="contents">
<div id="contents-body">
<div id="main">
<div class="padT12 marB10 clearFix">
<table class="boardFin yjSt marB6">
<tbody>
<tr>
<td>
ここに基準価格とか

取得したいデータ位置を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でスクレイピングのメモ

75
83
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
75
83