Pour extraire des données de documents HTML,
on dérive une classe de SGMLParser et on
définit des méthodes pour chaque balise ou entité que l’on souhaite
traiter.
La première étape pour extraire des données d’un document
HTML est d’obtenir le HTML. Si
vous avez un fichier HTML, vous pouvez le lire à l’aide des fonctions de fichier, mais le plus
intéressant est d’obtenir le HTML depuis des sites
web.
Le module urllib
fait partie de la bibliothèque standard de
Python. Il comprend des fonctions
permettant d’obtenir des information et des données à partir
d’URLs (principalement des pages web).
L’usage le plus simple de urllib est de lire le texte complet
d’une page web à l’aide de la fonction
urlopen. L’ouverture d’une
URL est semblable à l’ouverture d’un fichier. La
valeur de retour de urlopen est un objet
semblable à un objet-fichier et dont certaines méthodes sont les
mêmes que celles d’un objet-fichier.
La chose la plus simple à faire avec l’objet retourné par
urlopen est d’appeler
read, qui lit l’ensemble du code
HTML de la page web en une chaîne unique.
L’objet permet également l’emploi de
readlines, qui lit le code ligne par ligne et
le stocke dans une liste.
Quand vous n’en avez plus besoin, assurez vous de fermer
l’objet par un close, comme pour un objet
fichier.
Nous avons maintenant l’ensemble du code
HTML de la page d’accueil de http://diveintopython.org/ dans
une chaîne et nous sommes prêts à l’analyser.
from sgmllib import SGMLParser
class URLLister(SGMLParser):
def reset(self):
SGMLParser.reset(self)
self.urls = []
def start_a(self, attrs):
href = [v for k, v in attrs if k=='href'] if href:
self.urls.extend(href)
reset est appelé par la méthode
__init__ de SGMLParser
et peut également être appelé manuellement quand une instance de
l’analyseur a été créée. Donc, si vous avez une quelconque
initialisation à faire, faites la dans reset
et pas dans __init__, de manière à ce que la
réinitialisation se fasse correctement lorsque quelqu’un réutilise
une instance de l’analyseur.
start_a est appelé par
SGMLParser à chaque fois qu’il trouve une
balise <a>. La balise peut contenir un
attribut href et/ou d’autres attributs comme
name ou title. Le paramètre
attrs est une liste de tuples,
[(attribut,
valeur),
(attribut,
valeur), ...]. La balise peut
aussi être un simple <a>, ce qui est une
balise HTML valide (bien qu’inutile), dans ce
cas attrs sera une liste vide.
Les comparaisons de chaînes comme
k=='href' sont toujours sensibles à la casse,
mais ça ne pose pas de problème ici car
SGMLParser convertit les noms d’attributs
en minuscules lors de la création de
attrs.
Exemple 8.7. Utilisation de urllister.py
>>> import urllib, urllister>>> usock = urllib.urlopen("http://diveintopython.org/")>>> parser = urllister.URLLister()>>> parser.feed(usock.read())>>> usock.close()>>> parser.close()>>> for url in parser.urls: print urltoc/index.php
#download
#languages
toc/index.php
appendix/history.php
download/diveintopython-html-5.0.zip
download/diveintopython-pdf-5.0.zip
download/diveintopython-word-5.0.zip
download/diveintopython-text-5.0.zip
download/diveintopython-html-flat-5.0.zip
download/diveintopython-xml-5.0.zip
download/diveintopython-common-5.0.zip
... nous coupons la suite pour rester bref ...
Appelez la méthode feed, définie dans
SGMLParser, pour charger le code
HTML dans l’analyseur.[3] La méthode prend une chaîne en argument, ce qui est
ce que usock.read() retourne.
Comme pour les fichiers, vous devez fermer vos objets
URL par close dès que vous
n’en avez plus besoin.
Vous devez également fermer l’objet analyseur par
close, mais pour une raison différente. La
méthode feed ne garantit pas qu’elle traite
tout le code HTML que vous lui passez, elle
peut la garder dans un tampon en attendant que vous lui en passiez
plus. Quand il n’y en a plus, appelez close
pour vider le tampon et forcer l’analyse de tout le code.
Une fois le parser fermé par close,
l’analyse est complète et parser.urls contient
une liste de toutes les URLs pour lesquelles il
y a un lien dans le document HTML.
Footnotes
[3] Le terme technique pour un analyseur comme
SGMLParser est
consommateur: il consomme du
HTML est le décompose. On peut penser que
le nom de feed (nourrir) a été choisi
pour cadrer avec ce modèle du «consommateur».
Personnellement, ça me fait penser à une cage sombre dans un
zoo, sans arbres ni plantes ni trace de vie d’aucune sorte,
mais où vous pouvez deviner, si vous vous tenez tout à fait
immobile, deux yeux en vrilles qui vous regardent en retour
dans le coin du fond à gauche, mais vous arrivez à vous
convaincre que c’est votre esprit qui vous joue des tours et
la seule chose qui vous permet de dire que ce n’est pas une
cage vide est une petite pancarte sur la rambarde sur laquelle
est écrit «Ne pas nourrir l’analyseur.» Mais
peut-être que j’ai trop d’imagination. De toute manière, c’est
une image mentale intéressante.