Mon premier script Perl: utiliser & # 8220; obtenir ($ url) & # 8221; méthode dans une boucle?

StackOverflow https://stackoverflow.com/questions/467104

  •  19-08-2019
  •  | 
  •  

Question

Cela semblait donc assez facile. Utilisez une série de boucles imbriquées pour parcourir une tonne d'URL triées par année, par mois et par jour, puis téléchargez les fichiers XML. Comme il s’agit de mon premier script, j’ai commencé par la boucle; quelque chose de familier dans n'importe quelle langue. Je l'ai lancé en imprimant simplement les URL construites et cela a fonctionné parfaitement. J'ai ensuite écrit le code pour télécharger le contenu et le sauvegarder séparément, ce qui a parfaitement fonctionné avec un exemple d'URL sur plusieurs scénarios de test. Mais lorsque j'ai combiné ces deux morceaux de code, le programme est tombé en panne, le programme est resté bloqué et n'a rien fait du tout. J'ai donc lancé le débogueur et au fur et à mesure, je suis resté bloqué sur cette ligne:

  

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

Si je tape juste r pour quitter le sous-programme, cela fonctionne et continue vers un autre point avant de redescendre dans la pile d'appels où quelque chose de similaire se répète encore et encore pendant un certain temps. La trace de la pile:

  

$ = warnings :: register :: import ('warnings :: register') appelé à partir du fichier `/usr/lib/perl/5.10/Socket.pm 'ligne 7

     

$ = Socket :: BEGIN () appelé depuis le fichier `/usr/lib/perl/5.10/Socket.pm ', ligne 7

     

$ = eval {...} appelé à partir du fichier `/usr/lib/perl/5.10/Socket.pm ', ligne 7

     

$ = nécessite 'Socket.pm' appelé à partir du fichier `/usr/lib/perl/5.10/IO/Socket.pm 'ligne 12

     

$ = IO :: Socket :: BEGIN () appelé à partir du fichier `/usr/lib/perl/5.10/Socket.pm ', ligne 7

     

$ = eval {...} appelé à partir du fichier `/usr/lib/perl/5.10/Socket.pm ', ligne 7

     

$ = nécessite "IO / Socket.pm" appelé à partir du fichier "/usr/share/perl5/LWP/Simple.pm" ligne 158

     

$ = LWP :: Simple :: _ trivial_http_get ('www.aDatabase.com', 80, '/sittings/1987/oct/20.xml') appelé à partir du fichier `/ usr / share / perl5 / LWP / Simple .pm 'ligne 136

     

$ = LWP :: Simple :: _ get (' http: // www. aDatabase.com/1987/oct/20.xml ') appelée à partir du fichier `xmlfetch.pl' ligne 28

Comme vous pouvez le constater, il se bloque dans le " get ($ url) " méthode, et je n'ai aucune idée pourquoi? Voici mon code:

#!/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++;
    }

Je suis presque sûr que c'est quelque chose de petit que je ne sais tout simplement pas, mais Google n'a rien révélé.

Merci d'avance,

B.

MODIFIER: il est officiel, il reste bloqué pour toujours dans cette méthode get, s'exécute pendant plusieurs boucles, puis se bloque à nouveau pendant un certain temps. Mais c'est toujours un problème. Pourquoi cela se produit-il?

Était-ce utile?

La solution

Depuis http://www.adatabase.com/1987/oct/20. xml est un 404 (et de toute façon, ce n'est pas quelque chose qui peut être généré par votre programme (pas de "sous-titre" dans le chemin), je suppose que ce n'est pas le lien réel que vous utilisez, ce qui le rend En règle générale, utilisez example.com au lieu de créer des noms d’hôte, c’est pourquoi il est réservé.

Vous devriez vraiment

use strict;
use warnings;

dans votre code - cela aidera à mettre en évidence tous les problèmes de portée que vous pourriez avoir (je serais surpris si c'était le cas, mais il est possible qu'une partie du code LWP dérange avec votre $ urlBase ou quelque chose ). Je pense que cela devrait être suffisant pour changer les déclarations de variable initiale (et $ newUrl, $ content et $ filename) pour mettre 'mon' devant pour rendre votre code strict.

Si vous utilisez strict et que les avertissements ne vous rapprochent pas d'une solution, vous pouvez avertir le lien que vous êtes sur le point d'utiliser pour chaque boucle. Ainsi, vous pourrez l'essayer dans un navigateur et voir ce qu'il se passe, ou alternativement. L'utilisation d'un renifleur de paquets (telle que Wireshark ) peut vous donner des indices.

Autres conseils

(2006 - 1986) * 12 * 31 correspond à plus de 7 000. Demander des pages Web sans pause n'est pas agréable.

Version légèrement plus similaire à Perl (style code):

#!/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
            }
        }
    }
}

LWP a une fonction getstore qui effectue la majeure partie de la récupération puis de la sauvegarde du travail pour vous. Vous pouvez également consulter LWP :: Parallel :: UserAgent et un peu plus de contrôle sur la cliquez sur le site distant.

Je n'ai pas encore utilisé Perl, mais à première vue, je me demande si l'exception est levée à la suite d'une erreur 404. J'imagine que la fonction renverrait simplement undef si la réponse HTTP était soit une 404, 403, une redirection, etc., mais peut-être que ce n'est pas le cas.

Je pourrais recommander d'utiliser wget pour cela. Quelque chose comme `wget $ url` je pense que cela fonctionnerait.

Quoi qu'il en soit, comme je l'ai dit, je ne suis pas un programmeur Prl, mais puisque le lien que vous avez posté est en fait un lien 404, c'est ce que je suppose.

Faites-moi savoir si vous trouvez que c'est le problème.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top