Yahooファイナンスをスクレイピングして株価を抽出する

Yahoo!ファイナンスのウェブサイトをスクレイピングして、株価を抽出します。今回は、「日経平均株価」を対象としてスクレイピングを行います。

yahoo-stock-price

上図の黄色い丸で囲んだ場所から、日経平均株価の値を抽出してみます。

今回も、以下のツールを使ってスクレイピングを行います。

  • Python(2.7.5)
  • Beautiful Soup(4.4.0)

Beautiful Soupの詳しい使い方については、公式ドキュメントを参照してください。

Beautiful Soup Documentation — Beautiful Soup 4.4.0 documentation

さて、日経平均株価のページのソースコードを見ると、以下のようなテーブルの中に株価が記載されていることがわかります。

<table class="stocksTable" summary="株価詳細">
<tr>
<th class="symbol"><h1>日経平均株価</h1></th>
<td class="stoksPrice realTimChange">
<div class="realTimChangeMod">
</div>
</td>
<td class="stoksPrice">18,374.00</td>
<td class="change"><span class="yjSt">前日比</span><span class="icoDownRed yjMSt">-76.98(-0.42%)</span></td>
</tr>
</table>

どうやら<td class=”stoksPrice”>というタグに囲まれた値を抽出すれば良さそうです。この値を抽出するには、Beautiful Soupのfindメソッドを使ってfind(“td”,class_=”stoksPrice”)とすれば良さそうですが、これだと1個目の<td class=”stoksPrice realTimChange”>という部分を取得してしまいます。

検索条件を工夫してさらに絞り込みを行っても良いですが、ソースコードを良く読んでみると、<td class=”stoksPrice realTimChange”>タグには中身が無いので、中身が無ければ読み飛ばす、という処理を入れれば目的の株価だけを取得できそうです。find_allメソッドを使います。

# -*- coding: utf-8 -*-

import urllib2
from bs4 import BeautifulSoup

code = u"998407.o"
url = u"http://stocks.finance.yahoo.co.jp/stocks/detail/?code=" + code
html = urllib2.urlopen(url)
soup = BeautifulSoup(html, "lxml")

# 株価を取得
# td class="stoksPrice"を検索
for price in soup.find_all("td", class_="stoksPrice"):
    if price.string:
        print "Yahoo! ファイナンスから株価を取得しました。"
        # 抽出結果を文字列として格納、桁区切りを削除
        stockPrice = str(price.string).replace(',', '')
        if stockPrice.replace('.', '', 1).isdigit():
            stockPrice = float(stockPrice)
            print "株価を数値として格納しました。"
            print "株価:" + str(stockPrice)
        else:
            print "株価を数値として格納できませんでした。"

URIを指定する部分を2行に分けているのは、codeの値を書き換えて他の株価の値を抽出できるようにしているためです。

code = u"998407.o"
url = u"http://stocks.finance.yahoo.co.jp/stocks/detail/?code=" + code

また、抽出した株価を利用する場合のことを考えてfloat型で持っておきたいので、ゴチャゴチャと処理をしてfloat型で持てるようにしています。Beautiful Soupで抽出した値はそのままでは処理できないっぽい、桁区切りのカンマが邪魔である、という理由からstr型にキャストしたりカンマを削除したりした後、isdigitメソッドを使ってfloat値かどうかの判定を行った上で、float型として保持させています。

        stockPrice = str(price.string).replace(',', '')
        if stockPrice.replace('.', '', 1).isdigit():
            stockPrice = float(stockPrice)

Pythonで文字列がfloat型で保持できるやつかどうかを判定するためには、正規表現を使って判定するのが厳密っぽいですが、今回はもっと適当な方法でfloat型の判定を行っています。今回は適当でも大丈夫だと思います。

参考:

isdigit()について – 主にプログラムを勉強するブログ

昨日のエントリの補足+α – 主にプログラムを勉強するブログ

関係ないですが、コードの末尾についている.oとか.tとかの拡張子みたいな記号は何でしょうか?これが無ければ話はもっと簡単になるんですが…。気が向いたら後で調べてみたいと思います(※調べました)。

20行ほどのコードでYahooファイナンスから株価を取得することができました。あんまりアクセスしすぎると怒られるかもしれないので、もしこのスクリプトを試す方は常識の範囲内&自己責任でどうぞ。

Yahooファイナンスの拡張子の意味

この記事を公開した後、「Yahooファイナンスの拡張子は取引市場を表している」ということを教えていただきました。

検索してもなかなかそれらしい情報が出てきませんでしたが、Yahooファイナンスのヘルプに少しだけ書いてありました。

Yahoo!ファイナンスヘルプ – 株価の検索方法

市場 拡張子 正式名称
東証 .t 東京証券取引所
(マザーズ、JASDAQ、外国株市場を含む)
名証 .n 名古屋証券取引所(セントレックスを含む)
札証 .s 札幌証券取引所(アンビシャスを含む)
福証 .f 福岡証券取引所(Q-Boardを含む)

複数の市場に上場している銘柄を検索した場合は、代表市場の価格が表示されます。複数の市場に上場している銘柄で、代表市場以外の市場での株価を表示したい場合は、その市場を特定する拡張子を証券コードの末尾につけてください。

Yahooファイナンスをスクレイピングして株価を抽出するスクリプト on GitHub

Yahooファイナンスをスクレイピングして株価を抽出するスクリプトの最新版は、GitHub上で公開しています。このコードを使っていただいたら、ついでにGitHubのフォロー、スターをしていただけると励みになります!

Yahooファイナンスをスクレイピングして株価を抽出するスクリプト on GitHub

シェアしてもらえるとうれしいです。゚(´っωc`)゚。