編集(管理者用) | 編集 | 差分 | 新規作成 | 一覧 | RSS | 表紙 | 検索 | 更新履歴

Mojo::UserAgentで並行リクエスト

Mojo::UserAgentで並行リクエストを行なう場合の例。Mojolicious-2.70 で確認。

以下はカレントディレクトリ配下に images というディレクトリを作り、そこに $url で指定したページの画像(img要素)をダウンロードします。

#!perl
use strict;
use warnings;
use feature qw(say);

use Mojo::UserAgent;
use List::MoreUtils qw( uniq );
use Errno qw( EEXIST );

# ディレクトリが無ければ作成
my $dir = 'images';
unless (mkdir $dir or $! == EEXIST) {
    die "cannot create $dir: $!";
}

# ページをGET
my $url = 'http://www.example.com/';
my $ua = Mojo::UserAgent->new;
$ua->max_redirects(5);
my $tx = $ua->get($url);

# ページ内のimg要素のsrc属性を取得
my @srcs;
$tx->res->dom('img')->each(sub {
    push @srcs, $_[0]->{src};
});
@srcs = uniq @srcs;

# src属性を絶対URLに変換
my $base_url = $tx->req->url;
for my $src (@srcs) {
    $src = Mojo::URL->new($src);
    if (!$src->is_abs) {
        $src = $src->to_abs($base_url);
    }
}
say for @srcs;

# Blocking parallel requests
my $delay = Mojo::IOLoop->delay;
my $store = sub {
    my ($ua, $tx) = @_;
    my $file = $tx->req->url->path->parts->[-1];
    my $asset = $tx->res->content->asset;
    $asset->move_to("$dir/$file");
    say "$file saved!";
    $delay->end;
};
for my $src (@srcs) {
    $delay->begin;
    $ua->get($src => $store);
}
$delay->wait;