我需要从许多Web数据提供程序中获取一些数据,这些数据提供程序不公开任何服务,因此我必须编写类似这样的内容,例如使用WWW :: Mechanize:
use WWW::Mechanize;
@urls = ('http://www.first.data.provider.com', 'http://www.second.data.provider.com', 'http://www.third.data.provider.com');
%results = {};
foreach my $url (@urls) {
$mech = WWW::Mechanize->new();
$mech->get($url);
$mech->form_number(1);
$mech->set_fields('user' => 'myuser', pass => 'mypass');
$resp = $mech->submit();
$results{$url} = parse($resp->content());
}
consume(%results);
是否有一些(可能很简单;-)方式将数据提取到常见的%结果变量,同时,即:并行地,从所有提供商?< / p>
答案 0 :(得分:25)
答案 1 :(得分:5)
看起来ParallelUserAgent就是你要找的。 p>
答案 2 :(得分:4)
好吧,您可以创建线程来执行此操作 - 具体请参阅perldoc perlthrtut
和Thread::Queue。所以,它可能看起来像这样。
use WWW::Mechanize;
use threads;
use threads::shared;
use Thread::Queue;
my @urls=(#whatever
);
my %results :shared;
my $queue=Thread::Queue->new();
foreach(@urls)
{
$queue->enqueue($_);
}
my @threads=();
my $num_threads=16; #Or whatever...a pre-specified number of threads.
foreach(1..$num_threads)
{
push @threads,threads->create(\&mechanize);
}
foreach(@threads)
{
$queue->enqueue(undef);
}
foreach(@threads)
{
$_->join();
}
consume(\%results);
sub mechanize
{
while(my $url=$queue->dequeue)
{
my $mech=WWW::Mechanize->new();
$mech->get($url);
$mech->form_number(1);
$mech->set_fields('user' => 'myuser', pass => 'mypass');
$resp = $mech->submit();
$results{$url} = parse($resp->content());
}
}
请注意,由于您将结果存储在哈希中(而不是将内容写入文件),因此您不需要任何类型的锁定,除非存在覆盖值的危险。在这种情况下,您需要通过替换
来锁定%results
$results{$url} = parse($resp->content());
与
{
lock(%results);
$results{$url} = parse($resp->content());
}
答案 3 :(得分:3)
尝试https://metacpan.org/module/Parallel::Iterator - 上周看到了一个关于它的非常好的演示文稿,其中一个例子是URL的并行检索 - 它也包含在pod示例中。它比手动使用线程更简单(虽然它使用下面的fork)。
据我所知,你仍然可以使用WWW::Mechanize
,但避免搞乱线程之间的内存共享。它是这个任务的更高级别的模型,可能会更简单一点,让@Jack Maney的机械化程序的主要逻辑保持不变。