WWW::Mixi::Scraper

いささか出遅れた感があるけれど、Web::ScraperXPathの練習代わりに書いてみた。使い方はこんな感じ。

use WWW::Mixi::Scraper;
my $mixi = WWW::Mixi::Scraper->new(
  email => 'foo@bar.com', password => 'password'
);

my @list = $mixi->parse('http://mixi.jp/new_friend_diary.pl');
my @list = $mixi->new_friend_diary->parse;

my @list = $mixi->parse('http://mixi.jp/new_bbs.pl?page=2');
my @list = $mixi->new_bbs->parse( page => 2 );

my $diary = $mixi->parse('/view_diary.pl?id=0&owner_id=0');
my $diary = $mixi->view_diary->parse( id => 0, owner_id => 0 );

返り値はいちおうWWW::Mixiのものに近くなるようにしてあるけれど、WWW::Mixiのソースを読みながら書いたわけではないので厳密に同じというわけではない。
WWW::Mixiとの違いとしては、

文字の扱い

WWW::Mixiはoctetのままごりごり。コードはeuc-jp。::Scraperの方はWWW::Mechanize::DecodedContentのおかげで内部的にはdecode済みのperl string。最終的に出力するときにはencodeを忘れずに。

タグの有無

Scraperの方は返り値にいっさいタグが含まれない。brとかimgとかごっそり消える。Plaggerとかを使って読む分にはあまり問題にはならないと思うけれど、mixiクローンとかマッシュアップサイトを作る用途には向かない。

HTMLの変更に対する強度

Scraperの方は、XPathで注目しているところ以外の属性が変わっても変更不要。クォートの有無が変わったとか新しい属性が追加されたくらいではいちいちコードを修正する必要はない。逆に、::Scraperの方は途中に注目しているのと同じ属性を持つブロックが挿入されると弱い。「足あと」のように、スクレープしている箇所にクラスとかIDがついていれば問題ないけれど、tableのwidthとかcellpaddingの値とかから無理矢理切り出している場合は、まったく別のブロックにあってもルールに違反しないものが追加されるとゴミとして混じってくる。また、ブロックの一部がごそっと別の場所に動かされたりするとまるごと取れなくなったりする。

※もっとも、いまは取ってきたHTMLをまるごとスクレープしているけれど、最初にコメントとかを利用してスクレープする範囲を狭めてからWeb::Scraperを通すようにすればもう少し話が簡単になるとは思う。

::ScraperはPluggable

お互いに、使いたいところだけ実装しましょう。需要のないところまで実装するつもりはないです(パッチ、プラグイン、その他歓迎)。

その他、::ScraperのはPODが英語とか、細かな差はいろいろありますが、その辺はコード参照ということで。