scraper CLI で遊ぶ その2

pushing Web::Scraper 0.13 that has code generation and more examples in eg/

http://twitter.com/miyagawa/statuses/243570942

今度はコード生成だそうで。0.12 もチェックしていなかったので、あわせて新機能を確認。scraper CLI で遊ぶ - へたっぴ日記の続きっぽく。
今日はスクエニYahoo!ファイナンスを題材に。

hetappi@violet ~
$ scraper 'http://quote.yahoo.co.jp/q?s=9684.t&d=t'

s コマンドで HTML ソースを表示。

scraper> s
<html>
  <head>
    <title> Yahoo!&#x30D5;&#x30A1;&#x30A4;&#x30CA;&#x30F3;&#x30B9; - 9684.t </title>
...
  </body>
</html>
scraper> 

いままではあらかじめブラウザかなんかでソースを確認してから実行していたけど、シェル上で簡単に確認できるようになったので便利!大きなものは見にくいので相変わらすブラウザで。

$tree 変数で解析済みのツリーが参照できる。

scraper> print $tree, "\n"
HTML::TreeBuilder::XPath=HASH(0x109f79fc)

自分で好きにいじっちゃって!ってことでしょうか。複雑で XPath で書けない(もしくは書き方がわからない…)時とかも使える。

scraper> system "wget $_->{src}" for grep { my $f = $_->{src}; $f =~ s!.+/!!; !(-f $f); } $tree->findnodes('//img')

前からだけどこんなのもある。普通使わないだろうけど細工?する時に使える。眠くなかったら最後に書く。眠いのでそのうち書く。

scraper> print $scraper, "\n"
Web::Scraper=HASH(0x108b5d84)
scraper> print $scraper->__ua, "\n"
LWP::UserAgent=HASH(0x109ddd08)

WARN は激しく便利。XPathCSS セレクタを修正しながらさっくり確認できる。

scraper> process '//table[@border="1"]/tr[2]/td[1]', WARN;
<td colspan="2" nowrap>&#x53D6;&#x5F15;&#x5024;<br />9/3 <b>3,570</b></td>
scraper> process '//table[@border="1"]/tr[2]/td[1]/b', WARN;
<b>3,570</b>
scraper>

で、 c コマンド。最後の入力(d や y などのコマンドは除く)から実行可能なコードを生成。

hetappi@violet ~
$ scraper 'http://quote.yahoo.co.jp/q?s=9684.t&d=t'
scraper> process '//table[@border="1"]/tr[2]/td[1]/b', price => 'text'
scraper> y
---
price: '3,570'
scraper> c
#!/usr/bin/perl
use strict;
use Web::Scraper;
use URI;

my $stuff   = URI->new("http://quote.yahoo.co.jp/q?s=9684.t&d=t");
my $scraper = scraper {
    process '//table[@border="1"]/tr[2]/td[1]/b', price => 'text';
};
my $result = $scraper->scrape($stuff);

XPath を修正していき正しく指定できたら 最後に c コマンドで実行用コードを生成する。あとは抽出結果を好きなよう編集すればよい。

c all で全ての入力からコードを生成することも。

scraper> process '//table[@border="1"]/tr[2]/td[2]/font', diff => 'text'
scraper> y
---
diff: -20 (-0.56%)
price: '3,570'
scraper> c all
#!/usr/bin/perl
use strict;
use Web::Scraper;
use URI;

my $stuff   = URI->new("http://quote.yahoo.co.jp/q?s=9684.t&d=t");
my $scraper = scraper {
    process '//table[@border="1"]/tr[2]/td[1]/b', price => 'text';
    process '//table[@border="1"]/tr[2]/td[2]/font', diff => 'text';
};
my $result = $scraper->scrape($stuff);
scraper>

もう便利すぎ。