HTMLパーサ Hpricot
Hpricotとは?
Hpricotは Ruby用の HTML パーサです。スキャン部分は C 言語で書かれていて高速に動作します。 HTMLの解析や書き換えに威力を発揮する便利なライブラリです。
インストール
rubygemsを使うのが簡単です。
# gem install hpricot
すると以下のようにプラットフォームを聞いてきます。Unix系OSであれば 1 を、mswin32 であれば 2 を選びます。
Select which gem to install for your platform (i386-freebsd6) 1. hpricot 0.4 (ruby) 2. hpricot 0.4 (mswin32) 3. Cancel installation
コンパイルが始まり、インストールが行われます。
Building native extensions. This could take a while... ruby extconf.rb install hpricot ... Successfully installed hpricot-0.4
使い方
An Hpricot Showcase に、わかりやすくまとめられています。そこからいくつか抜粋します。
Hpricotのロード
rubygems を使っている場合、次のようにして Hpricotライブラリをロードし ます。
require 'rubygems' require 'hpricot'
HTMLページの読み込み
Hpricotメソッドにより、Hpricot::Docオブジェクトを生成します。 Hpricotはモジュール名であり、メソッド名でもあります。Hpricotメソッド は、Hpricot.parseと同等です。
doc = Hpricot("<p>A simple <b>test</b> string.</p>")
Hpricotメソッドの引数には文字列の他、IOオブジェクトを渡すこともできま す。open-uri を使って、webページを直接読み込ませることも可能です。
require 'open-uri'
doc = Hpricot(open("http://www.ruby-lang.org/"))
要素の検索
Hpricot::Doc#searchメソッドを使って、要素を検索できます。 searchの引数には、XPathあるいは CSS のセレクタを指定することができます。
以下の例では class="section" な div 要素を抜き出しています。
doc.search("div.section")
返ってくる値は Hpricot::Elementsオブジェクトです。
search の alias として '/' も使えます。
doc/"div.section"
inner_html
要素内の中身を得るには Hpricot::Elements#inner_htmlを使います。
(doc/'#elementID').inner_html
もし複数の要素がある場合、inner_htmlは全部の要素の中身を連結して返しま す。最初の要素の中身のみを得たいならば、以下のように first メソッドを 挟みます。
(doc/"div.section").first.inner_html
削除
Hpricot::Elements#remove で要素を削除できます。
(doc/'script').remove
HTMLへの変換
Hpricot::Elements#to_html で要素を HTML 文字列に変換できます。
(doc/"#elementID").to_html #=> "<div id='elementID'>...</div>"
ドキュメント全体も to_html で文字列化できます。
doc.to_html
ループ
Hpricot::ElementsはEnumerableであり、以下のようにして一要素ずつ処理す ることが可能です。
(doc/'a').each {|elem| puts elem.attributes['href']}
elem.attributes['href'] は elem['href'] と書くこともできます。 また、要素名や属性名は文字列以外にもシンボルが使えます。
doc 中の全 a タグの href 属性の配列を得るには以下のように書けます。
hrefs = (doc/:a).map {|elem| elem[:href]}
HpricotとWEBrickでコンテンツフィルタを作る
Rubyist Magazine に WEBrick でプロキシサーバを作って遊ぶ という記事がありました。
Ruby付属の WEBrickを使うと、ほんの数行で HTTP プロキシサーバを作ること ができます。また、ハンドラを書いてやることで、中継するHTMLの中身を書き かえることができます。Rubyist Magazine の記事中では、正規表現を使って slashdot.jp の上部の広告を削る方法を解説していました。 ここでは同等のことを Hpricotを使ってやってみます。
#!/usr/local/bin/ruby
require 'webrick'
require 'webrick/httpproxy'
require 'uri'
require 'rubygems'
require 'hpricot'
handler = Proc.new() {|req,res|
if req.host == 'slashdot.jp' and res.content_type =~ %r{text/html}
doc = Hpricot(res.body)
(doc/'table[@summary="advertise"]').remove
res.body.replace doc.to_html
end
}
s = WEBrick::HTTPProxyServer.new(
:Port => 8080,
:ProxyContentHandler => handler
)
Signal.trap('INT') do
s.shutdown
end
# サーバを起動する。
s.start
プロキシサーバ部分についての説明は Rubyist Magazine の記事を参考にして ください。記事中のコードと実質的に違っているのはハンドラ部分の以下の三 行です。
doc = Hpricot(res.body)
(doc/'table[@summary="advertise"]').remove
res.body.replace doc.to_html
res.body には中継する HTML の文字列が入っています。それを Hpricot のド キュメントオブジェクトに変換します。そして、広告が入っている table 要 素を削除して、res.body を広告が削除された HTML に置き換えています。
doc/'table[@summary="advertise"]'
というのは、table 要素のうち、summary属性が advertise のものを検索する という意味になります。slashdot.jpの上部の広告がこの要素に該当しますの で remove で取り除いています。
この例は単純な要素削除をやっているだけですが、Hpricotを使えばもっと複 雑な要素の加工や削除が可能です。

Keyword(s):
References:[FrontPage]