読者です 読者をやめる 読者になる 読者になる

さわだのノート

書籍のお仕事に役立つかもしれない思いつきを記録しています。

RSS: 記事の更新情報 Rss Feed

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の検索結果ページなどはこの通り、アクセスすることすらできませんでした。

f:id:takepierrot:20111226033602p:image

ちなみに、そのときのコードがこちら。

#!/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;
    }
);

動作を確認してみます。

f:id:takepierrot:20111226033603p:image

今度はうまくいってくれました。
僕はこれ以上凝った使い方はしそうにないので、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' );