Master 1 Plurital 2012
December 12 2012
Jusqu'à maintenant nous sommes arrivées à aspirer les pages web contenu dans plusieurs fichiers et stocker les liens vers les pages aspirées dans le tableau.
Le processus est le même qu'avec Bash. ll faudrait :
Une fois que nous avons vérifié que l'aspiration a été effectuée, nous pouvons procéder avec le dump du texte, la vérification de l'encodage et l'éventuelle conversion en utf-8. Les pages qui n'ont pas été aspirées ne peuvent pas nous servir pour les prochaines étapes.
Il existe plusieurs façons de récupérer des pages en python, et nous avons choisi le moyen qui ressemble le plus à l'ouverture des fichiers, avec urllib.open.
De première vue l'aspiration semble avoir bien marché, mais il faudrait récupérer les codes retours pour vérifier.
La bibliothèque URLlib dispose d'un moyen de récupérer le retour http qui indique si la requête a été bien effectuée. Nous avons vu en écrivant le script bash que ce code était bien plus utile que le code retour de la commande "curl", parce qu'il indiquait s'il y avait un problème aussi avec la récupération de la page voulue et non seulement un problème de l'exécution de la commande "curl". Pour récupérer le code, il suffit de faire :
httpcode=nomdemonflux.getcode()
En intégrant cette ligne dans la partie du script qui s'occupe de l'aspiration, nous pouvons voir le résultat de l'aspiration avec les codes retours correspondants :
flux=urllib.urlopen(ligne)
print u">>>URL numéro %d, dossier %s >>> début de l'aspiration >>>" %(i, filename),
codehttp = flux.getcode()
contenuhtml = flux.read()
flux.close()
print "done ! - http code : %d" %(codehttp)
Un code retour de 200 signifie qu'il n'y a pas d'erreur; quelque chose d'autre que 200 qu'il y en a...
Les deux erreurs retournées étaient 400 (Bad Request) et 404 (Page not Found). Cette dernière indique que la page n'existe plus et il faudrait abandonner l'URL.
Pour éviter d'attendre des heures pour certaines URLS qui prennent du temps à être aspirées, il est possible de spéficier un temps maximum - un timeout, si nous utilisons urllib2 :
flux=urllib2.urlopen(ligne , timeout=60)
Ici le temps maximum d'attente sera 60 seconds. Au-déla de 60 seconds, nous passerons à l'URL suivante.
Maintenant il semble y avoir un problème pour les erreurs comme 404 : Page not Found, qui ne sont plus envoyées au tableau, et qui apparaissent dans le terminal, en arrêtant le programme. Il semble s'agir d'une différence dans les manières que urllib et urllib2 traitent les erreurs - tandis que la réponse de urllib est de produire la page avec un message d'erreur et puis d'utiliser ce message d'erreur, urllib2 traite automatiquement l'exception en renvoyant à l'écran le message d'erreur suivant :
Nous avons besoin de récupérer cette erreur et de continuer avec l'aspiration des autres pages, malgré cette erreur.
Nous pouvons faire cela en utilisant la structure "try...except" pour gérer ces erreurs en continuant avec le traitement des autres URLs. Si nous voulons aussi récupérer le code retour http, il faudrait le récupérer avant URLError pour empêcher à ce que URLError traite aussi les erreurs HTTP du serveur.
URLerreur="-"
httperreur="-"
print u">>>URL numéro %d, dossier %s >>> "%(i, title),
try:
flux = urllib2.urlopen(ligne, timeout=1)
except socket.timeout as socketErreur:
print "\rURLErreur >>> %s" %(socketErreur)
print>>fichierin, "Page non aspirée"
print>>fichierin, " socket timeout"
i+=1
continue
except urllib2.HTTPError as httperreur:
print "Erreur http >>> %s" %(httperreur)
print>>fichierin, "Page non aspirée"
print>>fichierin, "%s" %(httperreur)
i+=1
continue
except urllib2.URLError as URLerreur:
print "\rURLErreur >>> %s" %(URLerreur.reason)
print>>fichierin, "Page non aspirée"
print>>fichierin, "%s" %(URLerreur.reason)
i+=1
continue
else:
codehttp = flux.getcode()
print u"début de l'aspiration >>>",
try :
contenuhtml = flux.read()
except socket.timeout as socketErreur:
flux.close()
print "URLErreur >>> %s" %(socketErreur)
print>>fichierin, "Page non aspirée"
print>>fichierin, " socket timeout"
else :
flux.close()
print "done ! - http code : %s" %(codehttp)
pageaspiree=open("./PAGES-ASPIREES/"+filename+"/page"+str(i)+".html", "w" )
print>>pageaspiree, contenuhtml
pageaspiree.close()
print>>fichierin, "< a href=\"../PAGES-ASPIREES/"+filename +"/page" + str(i) +".html\">page "+str(i)+"< /a>"
i+=1
Une dernière exception à été ajoutée - socket error, qui est renvoyée lorsqu'il y a un timeout. Il est nécessaire de traiter cette erreur avant l'aspiration (si urllib n'arrive pas à atteindre la page) et pendant l'aspiration (si urllib n'arrive pas à lire ce qu'il y a dedans). URLError tout seul ne semble pas suffire pour traiter cette erreur, donc il faut ajouter ces exceptions pour éviter que l'erreur soit renvoyer à stdout et que le programme s'arrête.
Dans le shell nous pouvons suivre la progression du programme avec le traitement des éventuelles erreurs. Le tableau résultant réflète ces erreurs comme avant avec le script bash, mais avec une seule colonne pour toutes les erreurs :
Nous voyons qu'une variété d'erreurs ont été traitées :
404 Page not Found
unknown url type: htp
socket timeout
Il y a quelques pages qui n'existent plus, qu'il faudrait abandonner. Dans le tableau ci-dessus, les deux premières étaient le résultat d'un sabotage de ma part de deux liens qui marchent d'habitude - pour tester le traitement des erreurs.
Nous voyons, donc, que les résultats des aspirations ne sont pas mal du tout !