Perl,如何从url并行获取数据?

时间:2011-07-25 09:36:27

标签: perl parallel-processing fetch

我需要从许多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>

4 个答案:

答案 0 :(得分:25)

答案 1 :(得分:5)

看起来ParallelUserAgent就是你要找的。

答案 2 :(得分:4)

好吧,您可以创建线程来执行此操作 - 具体请参阅perldoc perlthrtutThread::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的机械化程序的主要逻辑保持不变。