Web::Scraper

Today I've been thinking about what to talk in YAPC::EU (and OSCON if they're short of Perl talks, I'm not sure), and came up with a few hours of hacking with web-content scraping module using Domain Specific Languages.

使ってみたよ!

#!/usr/local/bin/perl
use strict;
use warnings;
use FindBin::libs;

use URI;
use Web::Scraper;
use Encode;
use List::MoreUtils qw/uniq/;

my $links = scraper {
    process 'a.keyword', 'keywords[]' => 'TEXT';
    result 'keywords';
}->scrape(URI->new(shift));

print encode('euc-jp', $_), "\n" for uniq @$links;
% perl scrape.pl http://d.hatena.ne.jp/hatenadiary/ | head -5
asterisk
techno
goth
プロフィール
アイコン

おおお miyagawa++。次いで http://d.hatena.ne.jp/secondlife/20060922/1158923779 にある Scrapi での例を Web::Scraper でやってみる。

#!/usr/local/bin/perl
use strict;
use warnings;
use FindBin::libs;

use URI;
use Web::Scraper;
use Encode;
use YAML;

my $links = scraper {
    process 'span.title > a:first-child', title => 'TEXT', url => '@href';
    process 'span.furigana', furigana => 'TEXT';
    process 'ul.list-circle > li:first-child > a', category => 'TEXT';
    result qw/title furigana url  category/
}->scrape(URI->new(shift));

warn encode('euc-jp', YAML::Dump($links));
% perl keyword_scraper.pl http://d.hatena.ne.jp/keyword/%BA%B0%CC%EE%A4%A2%A4%B5%C8%FE
---
category: アイドル
furigana: こんのあさみ
title: 紺野あさ美
url: /keyword/%ba%b0%cc%ee%a4%a2%a4%b5%c8%fe?kid=800

ばっちりですね。シンボルの書き方とかがちょっと違うところ以外は Ruby 版とほぼ等化。DSL 周りのドキュメントはまだないけどとりあえず scrapi のドキュメントを読めば ok! \(^o^)/

中の実装は HTML::TreeBuilder::Xpath + HTML::Selector::XPathXpath、シンボルテーブル hack で Perl DSL。HTTP::Response::Encoding が内蔵されてて取りに行く文字列の文字エンコーディングを気にしないでもいいのがささりげなくクライアントに優しい。ていうかコード短かいなあ、グレイト。