Модуль Parallel::ForkManager
должен работать на вас, но поскольку он использует fork
вместо потоков, переменные в родительском и каждом дочернем процессах являются отдельными, и они должны общаться по-другому.
Эта программа использует -o
вариант curl
, чтобы сохранить страницы в файлах. Файл, скажем, http://mysite.com/page
, сохраняется в файле http\mysite.com\page
и может быть извлечен оттуда родительским процессом.
use strict;
use warnings;
use Parallel::ForkManager;
use URI;
use File::Spec;
use File::Path 'make_path';
my $pm = Parallel::ForkManager->new(10);
foreach my $site (qw(http://mysite.com/page http://myothersite.com/page)) {
my $pid = $pm->start;
next if $pid;
fetch($site);
$pm->finish;
}
$pm->wait_all_children;
sub fetch {
my ($url) = @_;
my $uri = URI->new($url);
my $filename = File::Spec->catfile($uri->scheme, $uri->host, $uri->path);
my ($vol, $dir, $file) = File::Spec->splitpath($filename);
make_path $dir;
print `curl http://mysite.com/page -m 2 -o $filename`;
}
Update
Вот версия, которая использует threads
с threads::shared
вернуть каждую страницу в хэш разделяемой между всеми потоками. Хэш должен быть помечен как общий и заблокирован до его изменения, чтобы предотвратить одновременный доступ.
use strict;
use warnings;
use threads;
use threads::shared;
my %pages;
my @threads;
share %pages;
foreach my $site (qw(http://mysite.com/page http://myothersite.com/page)) {
my $thread = threads->new('fetch', $site);
push @threads, $thread;
}
$_->join for @threads;
for (scalar keys %pages) {
printf "%d %s fetched\n", $_, $_ == 1 ? 'page' : 'pages';
}
sub fetch {
my ($url) = @_;
my $page = `curl -s $url -m 2`;
lock %pages;
$pages{$url} = $page;
}
Вы хотите ограничить количество детей одновременно? – ikegami
Знаете ли вы список URL-адресов, прежде чем начать загрузку первого, или вы обнаружите новые URL-адреса при загрузке? – ikegami