Мой первый скрипт на Perl: использование метода "get ($ url)" в цикле?

Так что это казалось достаточно простым. Используйте серию вложенных циклов, чтобы пройти через тонну URL-адресов, отсортированных по году / месяцу / дню, и загрузить файлы XML. Поскольку это мой первый сценарий, я начал с цикла; что-то знакомое на любом языке. Я запустил его, просто распечатав построенные URL-адреса, и он работал отлично. Затем я написал код для загрузки содержимого и сохранения его отдельно, и он также отлично работал с образцом URL в нескольких тестовых случаях. Но когда я объединил эти два фрагмента кода, он сломался, программа просто застряла и вообще ничего не сделала. Поэтому я запустил отладчик, и когда я прошел через него, он застрял на этой одной строке:

warnings::register::import(/usr/share/perl/5.10/warnings/register.pm:25):25:vec($warnings::Bits{$k}, $warnings::LAST_BIT, 1) = 0;

Если я просто нажму r, чтобы вернуться из подпрограммы, она сработает и перейдет к другой точке, возвращаясь вниз по стеку вызовов, где что-то подобное происходит снова и снова в течение некоторого времени. Трассировка стека:

$ = warnings::register::import('warnings::register') called from file `/usr/lib/perl/5.10/Socket.pm' line 7

$ = Socket::BEGIN() called from file `/usr/lib/perl/5.10/Socket.pm' line 7

$ = eval {...} called from file `/usr/lib/perl/5.10/Socket.pm' line 7

$ = require 'Socket.pm' called from file `/usr/lib/perl/5.10/IO/Socket.pm' line 12

$ = IO::Socket::BEGIN() called from file `/usr/lib/perl/5.10/Socket.pm' line 7

$ = eval {...} called from file `/usr/lib/perl/5.10/Socket.pm' line 7

$ = require 'IO/Socket.pm' called from file `/usr/share/perl5/LWP/Simple.pm' line 158

$ = LWP::Simple::_trivial_http_get('www.aDatabase.com', 80, '/sittings/1987/oct/20.xml') called from file `/usr/share/perl5/LWP/Simple.pm' line 136

$ = LWP::Simple::_get('http://www.aDatabase.com/1987/oct/20.xml') called from file `xmlfetch.pl' line 28

Как видите, он застревает внутри метода get ($ url), и я понятия не имею, почему? Вот мой код:

#!/usr/bin/perl

use LWP::Simple;

$urlBase = 'http://www.aDatabase.com/subheading/';
$day=1;
$month=1;
@months=("list of months","jan","feb","mar","apr","may","jun","jul","aug","sep","oct","nov","dec");
$year=1987;
$nullXML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<nil-classes type=\"array\"/>\n";

while($year<=2006)
    {
    $month=1;
    while($month<=12)
        {
        $day=1;
        while($day<=31)
            {
            $newUrl = "$urlBase$year/$months[$month]/$day.xml";
            $content = get($newUrl);
            if ($content ne $nullXML)
                {
                $filename = "$year-$month-$day.xml";
                open(FILE, ">$filename");
                print FILE $content;
                close(FILE);
                }
            $day++;
            }
        $month++;
        }
    $year++;
    }

Я почти уверен, что это что-то крошечное, я просто не знаю, но Google ничего не обнаружил.

Заранее спасибо,

Б.

Обновлено: Официально, он просто навсегда зависает внутри этого метода get, выполняется несколько циклов, а затем снова зависает на некоторое время. Но это все еще проблема. Почему это происходит?

Понятия не имею, почему это не удается (ваш код выглядит нормально), но, пожалуйста, замените циклы while на циклы for (т.е. «for ($ year = 1987; $ year <= 2006; $ year ++)» или «for $ year. (1987 .. 2006) ».

nobody 22.01.2009 00:38

честный звонок. считать их замененными. облом об этом методе все же.

gnomed 22.01.2009 00:40

Пожалуйста, предоставьте 1. вывод perl -V, 2. номера версий для LWP :: Simple, Socket и IO :: Socket.

Alnitak 22.01.2009 00:55

также возможно, что удаленный сайт ограничивает скорость ваших запросов ...

Alnitak 22.01.2009 00:58

Я поддержу предложение Alnitak (целевой сайт ограничивает скорость, и функция "зависает" до истечения времени ожидания запроса).

Max Lybbert 22.01.2009 01:09

Всегда use strict и use warnings

Brad Gilbert 22.01.2009 01:59
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
6
6 993
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Я еще не использовал Perl, но на первый взгляд мне интересно, возникло ли исключение в результате ошибки 404. Я мог бы предположить, что функция просто вернет undef, если ответ HTTP был 404, 403, перенаправление и т. д., Но, возможно, это не так.

Я могу порекомендовать для этого использовать wget. Что-то вроде `wget $ url`, думаю, подойдет.

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

Сообщите мне, если вы обнаружите, что это проблема.

Это не так, я просто решил скрыть настоящую ссылку. он работает нормально, как я уже сказал, я тестировал метод get и сохранение отдельно. Когда на сайте нет дневной записи, он возвращает XML точно так же, как значение, которое я проверяю с помощью $ nullXML. Я попробую wget и посмотрю, работает ли он.

gnomed 22.01.2009 00:50

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

gnomed 22.01.2009 01:24
Ответ принят как подходящий

Поскольку http://www.adatabase.com/1987/oct/20.xml - это 404 (и не является чем-то, что может быть сгенерировано из вашей программы в любом случае (без `` подзаголовка '' в пути), я предполагаю, что это не настоящая ссылка, которую вы используете, что усложняет нам задачу. для тестирования. Как правило, используйте example.com вместо имени хоста, поэтому он зарезервирован.

Ты действительно должен

use strict;
use warnings;

в вашем коде - это поможет выделить любые проблемы с областью видимости, которые могут у вас возникнуть (я был бы удивлен, если бы это было так, но есть вероятность, что часть кода LWP возится с вашей $ urlBase или чем-то еще). Я думаю, этого должно быть достаточно изменить объявления исходных переменных (и $ newUrl, $ content и $ filename), чтобы поставить «my» впереди, чтобы сделать ваш код строгим.

Если использование strict и warnings не приближает вас к решению, вы можете предупредить ссылку, которую собираетесь использовать, каждый цикл, чтобы, когда он застрял, вы могли попробовать его в браузере и посмотреть, что произойдет, или, альтернативно, используя пакет сниффер (такой как Wireshark) может дать вам некоторые подсказки.

это сработало, добавив эти операторы использования и бросив «я» перед всем, и вот мы. Как я уже сказал, кое-что крошечное, чего я не знал. Большое спасибо, и извините, что я новичок в некоторых конвенциях, запомню на будущее.

gnomed 22.01.2009 01:19

@gnomed: example.com - это больше, чем просто соглашение, это RFC 2606.

jfs 22.01.2009 02:02

@gnomed: посмотрите Date :: Format и Date :: Parse; вы можете свернуть все циклы дат в один цикл и одновременно избегать таких дат, как «2005-02-31».

kyle 22.01.2009 09:58

(2006 - 1986) * 12 * 31 больше 7000. Запрашивать веб-страницы без паузы - нехорошо.

Немного более Perl-подобная версия (с точки зрения кода):

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

use LWP::Simple qw(get);    

my $urlBase = 'http://www.example.com/subheading/';
my @months  = qw/jan feb mar apr may jun jul aug sep oct nov dec/;
my $nullXML = <<'NULLXML';
<?xml version = "1.0" encoding = "UTF-8"?>
<nil-classes type = "array"/>
NULLXML

for my $year (1987..2006) {
    for my $month (0..$#months) {
        for my $day (1..31) {
            my $newUrl = "$urlBase$year/$months[$month]/$day.xml";
            my $content = "abc"; #XXX get($newUrl);
            if ($content ne $nullXML) {
               my $filename = "$year-@{[$month+1]}-$day.xml";
               open my $fh, ">$filename" 
                   or die "Can't open '$filename': $!";
               print $fh $content;
               # $fh implicitly closed
            }
        }
    }
}

Быстрое предупреждение: Perl незаметно преобразует диапазоны min..max в массив, а затем выдает итератор над ним (по крайней мере, ActivePerl в Windows). Сравните поведение min..max с (my $ i = min; $ i <max; ++ $ i), и оно примерно в 10 раз медленнее (по сравнению с моим последним тестом). Медленно переносил все свои скрипты :)

kyle 22.01.2009 09:55

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

gnomed 22.01.2009 12:03

@kyle: Вы используете старую версию Perl. for $i ($min..$max) быстрее и не потребляет больше памяти, чем for ($i=$min; $i<=$max; ++$i).

jfs 22.01.2009 14:17

LWP имеет функцию getstore, которая выполняет большую часть загрузки, а затем сохраняет работу за вас. Вы также можете проверить LWP :: Parallel :: UserAgent и немного больше контроля над тем, как вы попадаете на удаленный сайт.

Другие вопросы по теме