2013-05-19 5 views
0

Я использую Strawberry Perl в Windows XP для загрузки нескольких html-страниц, я хочу, чтобы каждый из них был переменным.perl, одновременно запуская больше процессов

Прямо сейчас я это делаю, но, как я вижу, он получает одну страницу в то время:

my $page = `curl -s http://mysite.com/page -m 2`; 
my $page2 = `curl -s http://myothersite.com/page -m 2`; 

Я посмотрел в Parallel :: ForkManager, но не смог заставить его работать. Также попытался использовать команду windows start до curl, но это не получает страницу.

Есть ли более простой способ сделать это?

+0

Вы хотите ограничить количество детей одновременно? – ikegami

+0

Знаете ли вы список URL-адресов, прежде чем начать загрузку первого, или вы обнаружите новые URL-адреса при загрузке? – ikegami

ответ

3

Модуль 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; 
} 
+0

на windows, Thread :: Pool может быть лучшим решением, чем эмулируемая вилка. – ysth

+0

Да, forking не работает хорошо на вдовы вообще (по крайней мере, не в то время, когда я это пробовал). –

+0

@ysth: Я никогда не уверен в статусе 'fork' в Windows. В дополнение к проблеме с переменными совместного использования, поэтому я добавил решение с помощью 'threads'. Я не вижу и не пользуюсь «Thread :: Pool» над стандартной прагмой. – Borodin

Смежные вопросы