Perl WWW :: Механизм Сравнение длины содержимого заголовка ответа разных URL-адресов

У меня есть вопрос, на который я надеюсь, что вы сможете помочь?

У меня есть два текстовых файла, содержащих следующее:

<Сильный> FILE1.TXT

http://www.dog.com/
http://www.cat.com/
http://www.antelope.com/

<Сильный> file2.txt

1
2
Barry

Результат, который я правильно достигаю, выглядит следующим образом:

http://www.dog.com/1
http://www.dog.com/2
http://www.dog.com/Barry 
http://www.cat.com/1
http://www.cat.com/2
http://www.cat.com/Barry
http://www.antelope.com/1 
http://www.antelope.com/2
http://www.antelope.com/Barry

Код для выполнения вышеуказанных

    open my $animalUrls, '<', 'FILE1.txt' or die "Can't open: $!";
    open my $directory, '<', 'FILE2.txt' or die "Can't open: $!";

    my @directory = <$directory>;   #each line of the file into an array
    close $directory or die "Can't close: $!";

    while (my $line = <$animalUrls>) {
    chomp $line;
    print $line.$_ foreach (@directory);
    push (@newListOfUrls, $line.$_) foreach (@directory);  #put each new url into array
    }

Теперь проблема, с которой я сталкиваюсь:

Мне нужно получить длину содержимого исходных URL-адресов (File1.txt) и сравнить Content-Length каждого из новых URL-адресов с соответствующим оригиналом, чтобы узнать, являются ли они одинаковыми или разными, например:

Код для получения Content-Length:

print $mech->response->header('Content-Length');  #returns the content length

У меня возникают проблемы с тем, как сравнить каждый новый URL-адрес с правильным соответствующим оригиналом? (т. е. не случайно сравнивая Content-Length http://www.cat.com/Barry с Content-Length http://www.dog.com/ ) Должен ли я использовать хэш может быть, и как я могу это сделать?

Ваша помощь с этим будет очень признательна, многие спасибо

1
nl ja de
@simbabque - Да, спасибо, было бы глупо игнорировать это :), какие-то мысли об этом?
добавлено автор perl-user, источник
@simbabque - Да, я понимаю, что вы сказали, единственная логика этого заключалась в том, что эта часть кода будет использоваться как часть гораздо более крупной программы, в которой я буду использовать много другого кода механизации, спасибо много :)
добавлено автор perl-user, источник
Кстати, я думаю, что WWW :: Mechanize может быть немного негабарит для этого. Если вы хотите только перейти к Content-Length, я бы просто использовал LWP :: UserAgent. Но поскольку Mechanize наследуется от LWP :: UserAgent, на самом деле это не очень важно. Если вы чувствуете себя более комфортно с Mechanize, придерживайтесь его.
добавлено автор simbabque, источник
Я рад, что вы приняли наш совет относительно открытия. Отлично сработано! :)
добавлено автор simbabque, источник

2 ответы

Вы должны использовать хеш для этого. Я бы изменил код ввода, чтобы создать более сложную структуру данных, поскольку это облегчает задачу.

open my $animalUrls, '<', 'FILE1.txt' or die "Can't open: $!";
open my $directory, '<', 'FILE2.txt' or die "Can't open: $!";

my @directory = <$directory>;   #each line of the file into an array
close $directory or die "Can't close: $!";
my $newURLs;

while ( my $baseURL = <$animalUrls> ) {
  chomp $baseURL;

  SUBDIR: foreach my $subdir (@directory) {
    chomp $subdir;
    next SUBDIR if $subdir eq "";
    # put each new url into arrayref
    push( @{ $newURLs->{$baseURL} }, $baseURL . $subdir );
  }
}

Теперь мы можем использовать это в наших интересах. Предполагая, что мы уже создали Механизм:

foreach my $url ( keys %{$newURLs} ) {
  # first get the base URL and save its content length
  $mech->get($url);
  my $content_length = $mech->response->header('Content-Length');

  # now iterate all the 'child' URLs
  foreach my $child_url ( @{ $newURLs->{$url} } ) {
    # get the content
    $mech->get($child_url);

    # compare
    if ( $mech->response->header('Content-Length') != $content_length ) {
      print "$child_url: different content length: $content_length vs "
        . $mech->response->header('Content-Length') . "!\n";
    }
  }
}

Вы даже можете сделать это без второго набора циклов foreach , поставив код, в котором вы создаете свою структуру данных.

Если вы не знакомы с этими ссылками, посмотрите perlreftut . Здесь мы делаем хэш с ключом для каждого из базовых URL-адресов и помещаем в него массив всех сгенерированных дочерних URL-адресов. Если вы используете Data :: Dumper для вывода окончательного $ newURLs , он будет выглядеть примерно так:

$VAR1 = {
  'http://www.dog.com/' => [
    'http://www.dog.com/1',
    'http://www.dog.com/2',
   ],
  'http://www.cat.com/' => [
    'http://www.cat.com/1',
    'http://www.cat.com/2',
   ],
};

EDIT: I updated the code. I used these files to test it:

URLS:

http://www.stackoverflow.com/ 
http://www.superuser.com/

Dirs:

faq
questions
/
3
добавлено
задал новый вопрос, спасибо
добавлено автор perl-user, источник
Кроме того, если бы я захотел в хранилище для последующего использования базового url, если длина содержимого не равна длине содержимого дочернего URL-адреса (а также просто распечатать, что они не совпадают, как показано в вашем коде), как бы вы пошли об этом (т. е. что это лучший способ сделать это?). Должен ли я просто использовать push @array, $ url или есть лучший, предпочтительный способ сделать это, например, используя другой хеш, большое спасибо
добавлено автор perl-user, источник
спасибо, именно то, что мне было нужно, я использовал next на наружном закрытии с меткой, я многому учусь из вашей помощи, спасибо
добавлено автор perl-user, источник
Привет, еще один вопрос: в цикле foreach, если он обнаружил, что http: //www.dog.com/1 имеет другую длину содержимого к исходному базовому URL-адресу http: //www.dog.com, как бы я тогда предотвратить он продолжал и проверял, имела ли еще http: //www.dog.com/2 другую длину контента (т. е. прекратить тестирование этого базового URL-адреса, как только он найдет один с другой длиной контента, а затем перейти к проверке http : //www.cat.com)? Дайте мне знать, если этот вопрос непонятен, большое вам спасибо за вашу помощь
добавлено автор perl-user, источник
Большое спасибо за обновление, это было очень полезно и прекрасно работает, и ваше объяснение вашего ответа велико, действительно помогло мне понять, что происходит. Что-то, с чем я не сталкивался, это SUBDIR: часть, я понимаю, что она делает, но что она называется, поэтому я могу посмотреть на некоторые документы/учебники для нее, еще раз спасибо.
добавлено автор perl-user, источник
Я думаю, что это может быть связано с частью $ mech-> get ($ url), которая пытается получить часть/1 или/2 или/Барри URL-адреса вместо http: //www.dog.com/1 или http: //www.dog.com/2 или http: //www.dog.com/Barry? Хотя я могу ошибаться
добавлено автор perl-user, источник
Я думаю, что это может быть связано с $ mech-> get ($ url); part as im get '400 URL должен быть абсолютным' и 'Использовать неинициализированное значение $ content_length в числовом ne (! =) в'
добавлено автор perl-user, источник
это именно то, что я искал :), я знаю, что вы сказали, что он непроверен, но я не могу заставить его работать правильно и не могу понять, почему, если у вас будет возможность его протестировать, я был бы чрезвычайно благодарен, благодаря
добавлено автор perl-user, источник
Я считаю, что что-то не так с вашей реализацией. Пожалуйста, разместите его в gist на gist.github.com , чтобы мы могли посмотреть.
добавлено автор simbabque, источник
@ perl-user я обновил код. Вы были правы, в этом была ошибка. Я использовал неправильные ключи для хэша, а также добавил пустые ключи. Вы могли бы подумать об этом, просто взглянув на Dumper $ newURLs. ;-)
добавлено автор simbabque, источник
@ perl-user SUBDIR: - это метка. Вы можете посмотреть perldoc.perl.org/perlsyn.html#Compound-Statements
добавлено автор simbabque, источник
Мой код не проверен. Там могут быть опечатки.
добавлено автор simbabque, источник
@ perl-user Либо next внешний цикл, либо last внутренний цикл. Я бы добавил метки к обоим петлям, как SUBDIR: , который я использовал в первом блоке кода.
добавлено автор simbabque, источник
@ perl-user Я потерял трек. Пожалуйста, задайте новый вопрос с примером кода и опишите, что вы хотите сделать.
добавлено автор simbabque, источник

Этот код, похоже, делает то, что вам нужно. Он сохраняет все URL-адреса в @urls и печатает длины содержимого, когда он извлекает каждый URL-адрес. Я не знаю, для чего вам нужны данные длины для потом, но я сохранил длину каждого ответа в хеше % lengths , чтобы связать их с URL-адресами.

use 5.010;
use warnings;

use LWP::UserAgent;

STDOUT->autoflush;

my @urls;

open my $fh, '<', 'FILE1.txt' or die $!;
while (my $base = <$fh>) {
  chomp $base;
  push @urls, $base;
  open my $fh, '<', 'FILE2.txt' or die $!;
  while (my $path = <$fh>) {
    chomp $path;
    push @urls, $base.$path;
  }
}

my $ua = LWP::UserAgent->new;

my %lengths;

for my $url (@urls) {
  my $resp = $ua->get($url);
  my $length = $resp->header('Content-Length');
  $lengths{$url} = $length;

  printf "%s  --  %s\n", $url, $length//'undef';
}

<Сильный> Выход

http://www.dog.com/  --  undef
http://www.dog.com/1  --  56244
http://www.dog.com/2  --  56244
http://www.dog.com/Barry  --  56249
http://www.cat.com/  --  156
http://www.cat.com/1  --  11088
http://www.cat.com/2  --  11088
http://www.cat.com/Barry  --  11088
http://www.antelope.com/  --  undef
http://www.antelope.com/1  --  undef
http://www.antelope.com/2  --  undef
http://www.antelope.com/Barry  --  undef
1
добавлено
Modern::Perl
Modern::Perl
362 участник(ов)

Пожалуйста, представьтесь при добавлении в группу. Это необходимо во избежание спам-ботов. Ваше первое сообщение не должно быть ссылкой или репостом. Мы всегда рады нестандартным вопросам.

use Perl or die;
use Perl or die;
164 участник(ов)

Группа о языке Perl и обо всём что с ним связано.

pro.perl
pro.perl
22 участник(ов)

Язык программирования Perl