Web::Queryに任意のUserAgentを設定する
Web::ScraperとWeb::Query
これまで、PerlでのスクレイピングにはWeb::Scraperを使ってきましたが、Web::Queryというモジュールもあるようです。
Web::Query - jQuery風にスクレイピング - ”><xmp>TokuLog 改メ tokuhirom’s blog
Webスクレイピング入門 - Perl Advent Calendar Japan 2011 Casual Track
Web::QueryではjQuery風にスクレイピングができるらしいです。僕はjQueryを使ったことがなかったのでどれくらい便利かは未知数でしたが、試してみるとたしかに書きやすい。スクレイピング中に、置換・代入などの処理が書けてしまうので、いちいちハッシュから値を取り出すといった回りくどい手順をとる必要もありません。
ただ、PODを見る限りではUserAgent設定用のメソッドは用意されていないようです。ちゃんとPC用ブラウザのUserAgentを設定しておかないと、正確にスクレイピングできないサイトもあるので、これは少々不便です。
Googleの検索結果ページなどはこの通り、アクセスすることすらできませんでした。
ちなみに、そのときのコードがこちら。
#!/usr/bin/perl use strict; use warnings; use utf8; use open IO => qw/:utf8 :std/; use Web::Query; my $url = 'http://www.google.com/search?q=Google日本語入力'; wq($url)->find('h3')->each(sub { my ($i, $wq) = @_; printf "%d %s\n", $i+1, $wq->text; } );
Web::Scraperで同様のコードを作り、UserAgentを設定して動作を試してみたところ、こちらは正常に結果が表示されました。ということは、原因はやはりUserAgentにありそうです。
モジュール内ではUserAgentをどのように扱っている?
とはいえ、UserAgentをまったく設定していないとも考えにくいので、モジュールの中では何らかの値が自動的に設定されているのでしょう。ソースを確認したところ、UserAgentは下記のように設定されているようです。
our $UserAgent = LWP::UserAgent->new(); sub __ua { $UserAgent ||= LWP::UserAgent->new( agent => __PACKAGE__ . "/" . $VERSION ); $UserAgent; }
グローパル変数で$UserAgentが設定されています。スクリプト側でこいつに任意の値を代入すれば、UserAgentを自由に設定することができそうです。
それを反映したコードがこちら。
#!/usr/bin/perl use strict; use warnings; use utf8; use open IO => qw/:utf8 :std/; use LWP::UserAgent; use Web::Query; my $ua = new LWP::UserAgent( agent => 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/534.30 '. '(KHTML, like Gecko) Chrome/12.0.742.16 Safari/534.30' ); $Web::Query::UserAgent = $ua; my $url = 'http://www.google.com/search?q=Google日本語入力'; wq($url)->find('h3')->each(sub { my ($i, $wq) = @_; printf "%d %s\n", $i+1, $wq->text; } );
動作を確認してみます。
今度はうまくいってくれました。
僕はこれ以上凝った使い方はしそうにないので、UserAgentの設定ができれば十分Web::Scraperの代わりとして利用できそうです。
追記
その後、PODを見たら思い切り設定方法が書いてありましたね。
気づけよっていう……。
HOW DO I CUSTOMIZE USER AGENT? You can specify your own instance of LWP::UserAgent. $Web::Query::UserAgent = LWP::UserAgent->new( agent => 'Mozilla/5.0' );