いくつかのURLを並行して取得し、何らかの作業を行うスクリプトを作成する必要があります。過去に私はいつもParallel::ForkManager
を使っていましたが、何か新しいことを学び、AnyEvent
(とAnyEvent::HTTP
または)という非同期プログラミングを試したかったのですが、AnyEventを理解し、行の後特定の例のperlでの非同期の理解
- (すべての行が別々のURLである)ファイルを開く
- (しかしFE 10の同時要求の制限と、並行して、今から)読み込み、ファイルの行(私はいけないロードしたいですメモリ全体のファイル - それは大きいかもしれません)
- HTTPリクエストを作成するfまたはそのURL
- は、応答を読ん
- アップデートMySQLのレコードに応じ
- (次のファイルの行)
私は、ブロッキングと非の違いを理解するために、私は多くのマニュアル、チュートリアルが、そのまだハードを読んだことがありますブロックコード。私は氏サボー基本を説明しhttp://perlmaven.com/fetching-several-web-pages-in-parallel-using-anyevent、で同様のスクリプトを発見したが、私はまだカントのようなものを実装する方法を理解する:
...
open my $fh, "<", $file;
while (my $line = <$fh>)
{
# http request, read response, update MySQL
}
close $fh
...
を...この場合、同時実行の制限を追加します。
私は助けのために非常に感謝される;)私はNet::Curl::Multi
試した池上のアドバイスに従い
UPDATE
。私は結果に非常に満足しています。同時に何千ものURLを取得するのにParallel::ForkManager
を使用した後、Net::Curl::Multi
はすばらしいようです。 ここに私のコードはwhile
loop with filehandleです。このようなことを書いたのは初めてのことだと思うが、経験豊富なPerlユーザーに見てみようと思って、潜在的なバグや欠けているものがあるかどうか教えてほしい。 また、もし私が尋ねることができます:Net::Curl::Multi
の同時実行性の仕組みを完全に理解していないので、MySQL UPDATEコマンド(DBI
経由)を入れて何か問題が起きるかどうか教えてください。RESPONSE
ループ約50台の同時実行スクリプトN::C::M
、多分もっと)。
#!/usr/bin/perl
use Net::Curl::Easy qw(:constants);
use Net::Curl::Multi qw();
sub make_request {
my ($url) = @_;
my $easy = Net::Curl::Easy->new();
$easy->{url} = $url;
$easy->setopt(CURLOPT_URL, $url);
$easy->setopt(CURLOPT_HEADERDATA, \$easy->{head});
$easy->setopt(CURLOPT_FILE, \$easy->{body});
return $easy;
}
my $maxWorkers = 10;
my $multi = Net::Curl::Multi->new();
my $workers = 0;
my $i = 1;
open my $fh, "<", "urls.txt";
LINE: while (my $url = <$fh>)
{
chomp($url);
$url .= "?$i";
print "($i) $url\n";
my $easy = make_request($url);
$multi->add_handle($easy);
$workers++;
my $running = 0;
do {
my ($r, $w, $e) = $multi->fdset();
my $timeout = $multi->timeout();
select $r, $w, $e, $timeout/1000
if $timeout > 0;
$running = $multi->perform();
RESPONSE: while (my ($msg, $easy, $result) = $multi->info_read()) {
$multi->remove_handle($easy);
$workers--;
printf("%s getting %s\n", $easy->getinfo(CURLINFO_RESPONSE_CODE), $easy->{url});
}
# dont max CPU while waiting
select(undef, undef, undef, 0.01);
} while ($workers == $maxWorkers || (eof && $running));
$i++;
}
close $fh;
私は、「コールバック関数の多くが設定されていないそうです" URLホストにドメインがある場合に表示されるようです。私がIPを使っているなら、このエラーは表示されません。また、私がf.e。 'print 'はそれを得ました!"; '#process $ easy'があるところでは、ページの内容が自動的に出力されます。 – alan
コンテンツを印刷するのではなく$ easyに保存するように修正しました。私はあなたが得るコールバックエラーを取得しないでください?[それを試してみてください。関連するかもしれません] – ikegami
助けてくれてありがとう。 Unfortunatelly私はまだ "コールバック関数が設定されていません"を取得します。実際には4回、あなたの 'printf'。私はそれがどこから来るか知りません。 – alan