概要
スクレイピングでやりたいことは、
だいたい以下のようなもの。
■データを取得する
-> GETでHTMファイルL/XML(RSS)ファイル/画像ファイルなどを取得
-> POSTでフォームにSubmitする(ログイン/パスワードDL)
-> 並列で取得する
■取得したデータから必要なデータを抽出する
-> HTMLをParseして、CSSセレクタでデータを抽出する
-> JSONをParseして、データを抽出する
-> XML(RSS)をParseして、データを抽出する
■取得したデータを保存する
-> ファイルとして保存する
Mojo::UserAgentは、上記の処理が簡単に書けるようになっている。
インストール
MojoliciousをインストールするとMojo::UserAgentも入る。
HTTPSにアクセスすることもあるので、IO::Socket::SSLも入れる。
$ cpanm Mojolicious IO::Socket::SSL
データを取得する
基本的な使い方は以下のようになる。
use strict;
use warnings;
use utf8;
use Mojo::UserAgent;
# インスタンス生成
my $ua = Mojo::UserAgent->new;
# 最大リダイレクト回数を設定
$ua->max_redirects(5);
# GET設定
my $tx = $ua->build_tx(GET => 'http://www.perl.com/');
# UserAgentを設定
$tx->req->headers->user_agent('user-agent');
# REFERERを設定
$tx->req->headers->referrer('http://www.perl.com/');
# Cookie設定
$tx->req->cookies({name => 'foo', value => 'bar'});
# トランザクションスタート
$tx = $ua->start($tx);
# 取得
# $res は、 Mojo::Message::Response
if (my $res = $tx->success) {
print $res->body;
}
else {
my ($err, $code) = $tx->error;
print $code ? "$code response: $err\n" : "Connection error: $err\n";
}
POSTを行う場合は、以下のようになる。
use strict;
use warnings;
use utf8;
use Mojo::UserAgent;
# フォームの値
my %params = (
login_id => 'hogehoge',
login_password => 'fugafuga',
);
# インスタンス生成
my $ua = Mojo::UserAgent->new;
# 最大リダイレクト回数を設定
$ua->max_redirects(5);
# POST設定
my $tx = $ua->build_tx(POST => 'http://hogehogehugahuga.com/login', form => \%params);
# REFERERを設定
$tx->req->headers->referrer('http://hogehogehugahuga.com/');
# トランザクションスタート
$tx = $ua->start($tx);
# 取得
# $res は、Mojo::Message::Response
if (my $res = $tx->success) {
print $res->body;
}
else {
my ($err, $code) = $tx->error;
print $code ? "$code response: $err\n" : "Connection error: $err\n";
}
取得したデータを扱う
jsonからデータを取得する場合は、
以下のように記述することができる。
# Pointerを指定してデータを取得する
my $title = $res->json('/results/0/title');
# hashに変換してから取得する
my $hash = $res->json
my $title = $hash->{results}[0]{title};
HTMLからデータを取得する場合は、
以下のように記述することができる。
# CSSセレクタで取得
# (セレクタを渡したdomメソッドの返り値はMojo::Collectionになっている)
# https://metacpan.org/pod/Mojo::Collection
my $texts = $res->dom('h2 > a')->text;
# メソッドチェーンで取得
my $texts = $res->dom->html->head->title->text;
ファイルを保存する場合は、
以下のように記述することができる。
use strict;
use warnings;
use utf8;
use Mojo::UserAgent;
# インスタンス生成
my $ua = Mojo::UserAgent->new->max_redirects(5);
# GETを設定
my $tx = $ua->get('latest.mojolicio.us');
# 取得
# $res は、Mojo::Message::Response
if (my $res = $tx->success) {
$res
->content # Mojo::Content::Single
->asset # Mojo::Asset::File
->move_to('/home/uchiko/mojo.tar.gz'); # ファイルを保存
}
else {
my ($err, $code) = $tx->error;
print $code ? "$code response: $err\n" : "Connection error: $err\n";
}
その他
non-blocking
POSTをnon-blockingで行える。
https://metacpan.org/pod/Mojo::UserAgent#post
Websocket
websocketも扱える。
https://metacpan.org/pod/Mojo::UserAgent#websocket
デバッグモード
MOJO_USERAGENT_DEBUG環境変数で、UserAgentの詳細な動作を確認することができる。
https://metacpan.org/pod/Mojo::UserAgent#DEBUGGING
Inactivity timeout
大きなデータを送っていると「Inactivity timeout」というエラーが出るかもしれない。
その時は以下のようにタイムアウト値を大きめに設定する。
http://mojolicio.us/perldoc/Mojolicious/Guides/FAQ#What_does_Inactivity_timeout_mean
$ MOJO_INACTIVITY_TIMEOUT=10000 perl scrape.pl
参考
Mojo::UserAgent
https://metacpan.org/pod/Mojo::UserAgent