FrontPage  Index  Search  Changes  Login

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 MagazineWEBrick でプロキシサーバを作って遊ぶ という記事がありました。

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を使えばもっと複 雑な要素の加工や削除が可能です。

Last modified:2006/08/27 19:29:18
Keyword(s):
References:[FrontPage]