scraper CLI で遊ぶ

via Web::Scraper プレゼン@YAPC::EU
Web::Scraperコマンドラインインタフェースが追加されたのでさっそく遊んでみた。お題は、オライリー・ジャパン発行書籍一覧から書籍情報の抽出。簡単杉…。
HTMLソースはこんなん。スクレイピング向きのきれいなソースだね。

...
<table class="booklist" width="100%" cellspacing="0" cellpadding="0" border="0">
 <tr class="booklist defaultcolor">
...
 </tr>

 <tr class="up">
  <td class="booklistisbn">
   <a name="4-87311-094-7" />
   4-87311-094-7
  </td>
  <td class="booklisttitle"><a href="../books/4873110947/">.NET Framework エッセンシャルズ第2版</a></td>
  <td class="booklistprice">\3,780</td>
 </tr>

 <tr class="down">
  <td class="booklistisbn">
   <a name="4-87311-128-5" />
   4-87311-128-5
  </td>
  <td class="booklisttitle"><a href="../books/4873111285/">802.11セキュリティ</a></td>
  <td class="booklistprice">\3,570</td>
 </tr>
...

んじゃ、実行。

$ scraper http://www.oreilly.co.jp/catalog/

URL 以外にもこんなのもあり。q は終了。

$ wget http://www.oreilly.co.jp/catalog/index.html
$ scraper index.html
scraper> q
$ cat index.html | scraper
scraper> q

抽出内容はおなじみの process で指定。

scraper> process '//tr[@class =~ /^(up|down)$/]', 'books[]' => scraper { ...

長いので略したけど実際はこれを1行で。

process '//tr[@class =~ /^(up|down)$/]', 'books[]' => scraper {
  process 'td.booklistisbn > a', 'isbn' => '@name';
  process 'td.booklisttitle > a', 'title' => 'text';
  process 'td.booklistprice', 'price' => 'text';
}

Term::ReadLine を使用しているのでシェルみたく履歴を呼び出せる。CSS セレクタXPath をちょこちょこ修正して試すのに便利。

d は Data::Dumper で結果をダンプ。日本語がコードで出ちゃうけど気にしない。

scraper> d
$VAR1 = {
  'books' => [
    {
      'price' => '\\3,780',
      'title' => ".NET Framework \x{30a8}\x{30c3}\x{30bb}\x{30f3}\x{30b7}\x{30e3}\x{30eb}\x{30ba}\x{7b2c}2\x{7248}",
      'isbn' => '4-87311-094-7'
    },
    {
...
    }
  ]
};
scraper>

y だと YAML::Dump で。環境によると思うけど Windows だと文字化けするかな。

scraper> y
---
books:
  - isbn: 4-87311-094-7
    price: '\3,780'
    title: .NET Framework 繧ィ繝・そ繝ウ繧キ繝」繝ォ繧コ隨ャ2迚
...
scraper>

scraper の ソースを見るとわかるけど、d、y、q 以外の入力は eval() で評価される。これを利用して出力の文字コードを変えちゃおう。warn で出力しているので STDERR ね。

scraper> binmode STDERR, ':encoding(sjis)'
scraper> y
---
books:
  - isbn: 4-87311-094-7
    price: '\3,780'
    title: .NET Framework エッセンシャルズ第2版

いいネタが浮かばないけど、perlsh(というか、perl -ne "eval")みたくやりたい放題。

scraper> print "$_\n" for map { ++$_ } (1 .. 5)
2
3
4
5
6
scraper>

結果は result で参照できるので、ファイルに書いたり、メモ帳で開いたり。

scraper> open FILE, '>:encoding(sjis)', 'books.txt'
scraper> print FILE Dump(result)
scraper> close FILE
scraper> system 'notepad books.txt'
scraper>

さすが miyagawa++。想定された使い方ではないかもだけど…。

2007/09/04 追記
scraper CLI で遊ぶ その2 - へたっぴ日記