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 - へたっぴ日記へ