Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Perl: Общие вопросы > Многопоточная проверка доменов


Автор: djusha 5.5.2011, 19:00
Необходимо проверить большое количество доменов по очереди на разных сайтах . 
То-есть из файла берем домен, в несколько потоков проверяем сначала на одном сайте... обрабатываем результаты проверки... ненужные домены отсеиваем,
Проверяем на другом сайте... снова обрабатываем, ненужные домены отсеиваем... и так несколько раз

Все это усложняется тем, что необходимо проверять через список прокси или с использованием нескольких IP адресов сервера ... один прокси \ IP адрес на один один поток

Как посылать запросы с конкретного IP или прокси... тут написано http://www.s3blog.org/lwp-socks.html, 

про многопоточность... вроде Coro http://forum.vingrad.ru/forum/topic-317827/unread-1/hl/anyevent/index.html
Или AnyEvent::HTTP::LWP::UserAgent - http://search.cpan.org/~tadam/AnyEvent-HTTP-LWP-UserAgent-0.07/lib/AnyEvent/HTTP/LWP/UserAgent.pm 

без многопоточности и без списка прокси \ IP все прекрасно работает, но с многопоточностью и списком проксей \ IP ... пардонте...ума никак не хватает все в кучу собрать

Как вставить в подпрограмму порцию УРЛ и прокси или IP...  Как принять результат для каждого УРЛ...

Вот пример с однопоточным вариантом ниже. подпрограммы checkOneSite и checkSecondSite проверяют домены с использованием LWP::UserAgent, тут все нормально и понятно
Не хватает ума собрать все в кучу с многопоточностью и списками прокси \ IP

Код

#!/usr/bin/perl
use strict;
 use warnings;

open (FIN, '<', 'domain.txt') || die 'No read file! \n';
open (my $fout, '>', 'domain_out.csv')  || die 'No write file! \n';

 my $countAll = '0'; my $countGood = '0';
# foreach my $domain ( @domains ) {
while (<FIN>){ # while читает построчно, и не вешает всю память при чтении больших файлов
# для многопоточной проверки надо бы здесь подавать порциями по числу потоков... скажем есть 10 прокси или IP хостера, значит 10 потоков... как?

  $countAll++; # считаем все домены
 my $domain = $_;
 chomp( $domain );

 my ($goodDomainOne, $oneParametr) = checkOneSite("$domain"); # нужна многопоточная проверка доменов по первому сайту. возвращаем успешнопройденный домен в $goodDomainOne и результат в $oneParametr, возможны еще какие то параметры кроме $oneParametr
# что нибудь делаем, проверяем
        if ($oneParametr) { # только успешнопройденные

 my ($goodDomainSecond, $secondParametr)  = checkSecondSite("$domain"); # нужна многопоточная проверка доменов по первому сайту. возвращаем успешнопройденный домен в $goodDomainSecond и результат в $secondParametr, возможны еще какие то параметры кроме $secondParametr
 # что нибудь  делаем
         if ($secondParametr) { # только успешнопройденные

  $countGood++; # считаем успешно прошедшие
 print {$fout} "$countAll;$countGood;$goodDomainOne;$oneParametr;$goodDomainSecond;$secondParametr\n";
 print             "$countAll;$countGood;$goodDomainOne;$oneParametr;$goodDomainSecond;$secondParametr\n";

            }
                      }
                                }

close ($fout);
close (FIN);


Автор: mishnik 5.5.2011, 22:21
djusha, 
поставьте squid
для каждого урла можно настроить свой прокси и логин/пароль

Автор: EcSYZ 6.5.2011, 21:00
Вот примерно так под AnyEvent будет. С проксями ничего думаю не подскажу, ибо с ними не заморачивался.
Код

#!/usr/bin/perl
$|=1;
use v5.10;
use strict;
use warnings;
use AnyEvent::HTTP;

#...
#подгрузка данных
my @good_site;
my @bad_site;

my $cv = AnyEvent->condvar;
my $count=0;#отвечает за кол-во не обработанных коллбэков
 
foreach my $link (@links){
   $count++;
   http_request(
      GET     => $link,
      headers => { "user-agent" => 'Opera/9.80 (X11; Linux x86_64; U; ru) Presto/2.8.131 Version/11.10' },
      timeout => 10,
      sub {
         if($_[1]->{Status}==200){
            push @good_site, $link;
         } else {
            push @bad_site, $link;
         }
         (--$count)==0 ? $cv->send : undef;
   };
}
$cv->recv;

Автор: djusha 7.5.2011, 07:21
Спасибо! с гор приеду после праздников, поразбираюсь... 

Автор: djusha 10.5.2011, 12:45
Цитата(EcSYZ @ 6.5.2011,  21:00)
Вот примерно так под AnyEvent будет. С проксями ничего думаю не подскажу, ибо с ними не заморачивался.

не сразу, но заработало... не была закрыта скобка http_request

кроме того, после проверки скрипт висит... не завершается...

и хотелось бы понять, как задать количество одновременных потоков... допустим хотелось бы чтобы скрипт обрабатывал по 10 доменов...

ну и в идеале, хотелось бы реализовать каждый поток на свой IP...

спасибо заранее!

Автор: EcSYZ 10.5.2011, 18:20
Сори, скрипт я набросал прямо тут на форуме, так что не проверял на работоспособность. Вообщем я хотел передать суть идеи  smile 
Код

#!/usr/bin/perl
$|=1;
use v5.10;
use strict;
use warnings;
use AnyEvent::HTTP;

my $threads=20;#кол-во одновременных запросов
my $threads_run=0;
$AnyEvent::HTTP::MAX_PER_HOST=$threads;#меняем дефолтное 4 на нужное нам кол-во одновременных запросов, т.е. 20

my @links;
my @good_site;
my @bad_site;

#...
#подгрузка данных
#...

&cycle_run;

sub cycle_run
{
   while(scalar @links != 0){
      my $cv = AnyEvent->condvar;

      for(1 .. $threads){
         #если ссылок больше нет, то не пытаемся больше стартовать запросы
            last if(scalar @links == 0);
            &run($cv, pop @links);
      }
      last if($threads_run == 0);
      $cv->recv;
   }
}

sub run
{
   my $cv   = shift;
   my $link = shift;

   $threads_run++;
   http_request(
      GET     => $link,
      headers => { "user-agent" => 'Opera/9.80 (X11; Linux x86_64; U; ru) Presto/2.8.131 Version/11.10' },
      #proxy => [$host, $port[, $scheme]]
      timeout => 10,
      sub {
         #разные действия
         (--$threads_run) == 0 ? $cv->send : undef;
      }
   );
}

Вот примерно так. &cycle_run занимается стартом запросов и их отловом, а &run чисто за запросы отвечает и действия с ними.
В &cycle_run 2 цикла - while отвечает за перебор всех ссылок, а for - за создание запросов пачками по N штук.

Автор: djusha 11.5.2011, 06:28
Спасибо! Будет над чем сегодня подумать!

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)