mk-mode BLOG

このブログは自作の自宅サーバに構築した Debian GNU/Linux で運用しています。
PC・サーバ構築等の話題を中心に公開しております。(クローンサイト: GitHub Pages

ブログ開設日2009-01-05
サーバ連続稼働時間
Reading...
Page View 合計
Reading...
今日
Reading...
昨日
Reading...

Ruby - Hpricot で Yahoo!ファイナンス!

[ プログラミング, 株式 ] [ Ruby ]

【はじめに】
Yahoo!ファイナンス掲載情報の自動取得(スクレイピング)は禁止されています。(参照
以下の記事を参考にすることもお勧めしません。

こんばんは。

当方、以前から Ruby + MySQL で Yahoo!ファイナンスから株価時系列データ等を取得して管理しています。 データの取得には Hpricot という Ruby 用の HTML パーサを使用しています。

しかし、時系列データがYahoo!ファイナンスのサイトにアップされる時間がまちまちなので、チェックするスクリプトを作成してみました。

こうした HTML から情報を取得する事を「Webスクレイピング」などと言います。

記録

普段使用している株価取得スクリプトの不要な部分を取り除いただけのシンプルなものにしました。

0. 前提条件

使用した Ruby は 1.9.3-p194 です。 CentOS 6.2、Cygwin 1.7.15 上で動作確認してます。 Windows は未確認です。文字コードあたりで不具合はあるかもしれません。 また、市場・銘柄によって時系列データが確定する時刻が異なる場合もあります。 大まかな目安として利用するのが目的です。

1. Ruby スクリプト

  • 特定の銘柄の時系列データの最新の日付を取得しています。
  • 1銘柄のデータが更新されていれば、全て更新されているものと判断するようにしています。
  • 取引が活発でない銘柄を設定すると、1日取引がない場合もあるので注意が必要です。
  • HTML を解析すると2番目の TABLE タグに時系列データが格納されているようです。
  • その TABLE タグ内の1番目の TR タグは表のヘッダー部分です。
  • 2番目の TR タグの1番目の TD タグが最新の日付であるものとして扱っています。
  • データが取得できなければ “9999-99-99” を返すようにしています。

※HTML の構成はサイトの修正で変更になる場合があるので要注意!

【 ファイル名:check_date.rb 】

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# -*- coding: utf-8 -*-
require 'hpricot'
require 'open-uri'

class CheckDate
  # 時系列データをチェックする銘柄(存在する銘柄)
  # (できれば取引が活発な銘柄)
  STOCK = "8473.T"
  # Webサイト情報 ( Yahoo!ファイナンス 時系列データの URL )
  URL   = "http://info.finance.yahoo.co.jp/history/?code="

  # [CLASS] Webデータ
  class WebData
    def initialize
      @last_date = "9999-99-99"
    end

    # 最終取引日付取得
    def get_date
      begin
        # HTML取得
        url =  URL + STOCK
        html = Hpricot( open( url, "r" ).read.encode( "utf-8", :invalid => :replace, :undef => :replace ) )

        # HTML 内 2番目の TABLE タグが存在しなければ終了
        # (2番目の TABLE タグに時系列データがある)
        table = html.search( "table" )[1]
        return @last_date unless table

        # 2番目の TABLE タグ内の2番目の TR タグが存在しなければ終了
        # (1番目の TR タグはヘッダ行)
        tr = table.search( "tr" )[1]
        return @last_date unless tr

        # 取引日取得
        # (1番目の TD タグに日付が格納されている)
        td = tr.search( "td" )[0]
        if td.inner_text =~ /(\d+)年(\d+)月(\d+)日/
          @last_date = "#{$1}-#{sprintf("%02d",$2.to_i)}-#{sprintf("%02d",$3.to_i)}"
        end

        return @last_date
      rescue => e
        # エラーメッセージ
        str_msg = "[ERROR][" + self.class.name + ".get_date] " + e.to_s
        STDERR.puts( str_msg )
        exit 1
      end
    end
  end

  # 最終取引日付取得
  obj_webdata = WebData.new
  date = obj_webdata.get_date
  puts "#{Time.now.strftime( "%Y-%m-%d %H:%M:%S" )} 現在: #{date}"
end

2. 動作確認

作成した Ruby スクリプトを実行すると以下のように出力されるはずです。

1
2
$ ruby check_date.rb
2012-06-21 23:50:48 現在: 2012-06-21

3. その他

当方は、このスクリプトをさらに改良し(結果をテキストファイルに出力するようにし)、サーバで1時間毎に cron 起動させ、何時ごろデータが更新されるかのチェックを行ったりもしています。

今回の日付チェックのみならず株価等のデータ取得も基本的な考えは同じです。 また、Ruby + Hpricot でなく Ruby + Nokogiri という方法もあります。 Nokogiri の方が高速という意見もあるようですが、当方が試行してみたところほぼ同じ速度でした。(Hpricot も改良されて速度が速くなってきている?)

参考サイト


当方は、Ruby + Hpricot での Web スクレイピングで以下の事も行っています。

  • アメダスデータの取得
  • 地方公共団体一覧の取得
  • 数字選択式宝くじのデータ取得

これらは当方のホームページで確認できます。→ mk-mode SITE

以上。

Comments