LoginSignup
21
20

More than 5 years have passed since last update.

Mojo::UserAgentがスクレイピングツールとして便利

Last updated at Posted at 2014-05-31

概要

スクレイピングでやりたいことは、
だいたい以下のようなもの。

■データを取得する
-> 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

データを取得する

基本的な使い方は以下のようになる。

sample1.pl
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を行う場合は、以下のようになる。

sample2.pl
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からデータを取得する場合は、
以下のように記述することができる。

jsonsample.pl
# Pointerを指定してデータを取得する
my $title = $res->json('/results/0/title');

# hashに変換してから取得する
my $hash = $res->json
my $title = $hash->{results}[0]{title};

HTMLからデータを取得する場合は、
以下のように記述することができる。

htmlsample.pl
# 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;

ファイルを保存する場合は、
以下のように記述することができる。

filesample.pl
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

21
20
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
21
20