2008年6月13日金曜日

Ruby の Hpricot でスクレイピング

1. scRUBYt! を使えない

Python で、スクレイピングをするのに Beautiful Soup を使った。

スクレイピングの対象は、気象庁の過去のデータ。具体的には、

「2008 年 1 月の東京の日ごと」の気象データが掲載されているページから、特定の観測対象のデータのみを抽出したい。ただし、抽出するとき、抽出データを後で表計算に貼り付けるため、「タブ区切り」にすること。対象の項目は、「現地の気圧」と「平均気温」とする。

同じ課題に対して、Ruby を使いたい。

Scrubyt は、

スクレイピング

という言葉を知ったきっかけとなった。

RubyGemsScrubyt をインストールはできた。しかし、Scrubyt を使うと、エラーが表示されてダメだった。

 

2. Hpricot でスクレイピング

Scrubyt を使うことは諦め、代わりに

を使ってみる。使い方は、以下を参考にした。

 

/ は search の別名

サンプルのコードには、普通のメソッドとは違った書き方がされている。

(doc/:a).each do |link|

これは、HTML の a タグを取得しているところ。

pylori*style wiki - HTMLパーサ Hpricot によると、

Hpricot::Doc#searchメソッドを使って、要素を検索できます。 searchの引数には、XPathあるいは CSS のセレクタを指定することができます。

以下の例では class="section" な div 要素を抜き出しています。

doc.search("div.section")

返ってくる値は Hpricot::Elementsオブジェクトです。

search の alias として '/' も使えます。

doc/"div.section"

/ は search の別名として定義されている。

lib/hpricot/elements.rb at master from hpricot/hpricot - GitHub

alias_method :/, :search

よって、

(doc/:a)

と書いているコードは、以下と同じ。

(doc./(:a))

これは、

1 + 2

が、以下と同じであることと同じ。

1.+(2)

 

ソースコード

早速書いてみる。

require 'hpricot'
require 'open-uri'

doc = Hpricot(open("http://www.data.jma.go.jp/obd/stats/etrn/view/daily_s1.php?prec_no=44&prec_ch=%93%8C%8B%9E%93s&block_no=47662&block_ch=%93%8C%8B%9E&year=2008&month=01&day=12&view=p1"))

DATE_FROM = 1
DATE_TO = 5

records = []
(doc/"tr.mtx").each do |tr|
  rec = []
  (tr/"div#a_print").each do |div|
    rec << (div/:a).inner_html.strip
  end
  (tr/"td.data_0_0").each do |td|
    rec << td.inner_html.strip
  end
  records << rec if not rec.empty?
end

records.each do |rec|
  next unless (DATE_FROM..DATE_TO).include?(rec[0].to_i)
  rec.each_with_index do |d,i|
    print d ,"\t" if [1,6].include?(i)
  end
  puts
end

/ を search の別名として使えるので、コードが書きやすいし、読みやすい。 ^^