Python et traitement HTML
Python dispose d'un outil pour traiter un fichier HTML avec le module HTMLParser. Voici une introduction à son usage.
Exercice d'apprentissage
Pour que le documentation ne soit pas purement théorique, choisissons-nous un exercice.Prenons une page de résultat de recherche d'un moteur de recherche quelconque (choisissons Yahoo!) et essayons de voir à quel rang se trouve un site (un domaine) sur cette premiere page.
Etude de la "page"
Une page de résultats Yahoo est structurée de la manière suivante: Chaque resultat est contenu dans un DIV de classe "res" (appelons cela un DIV-"res").Dans chaque DIV-"res", le domaine est mentionné deux ou trois fois:
- Le vrai lien
- Le lien vers un outil de traduction de la page
- Le lien vers une version en cache quand il y en a
Algorithme
Nous allons décompter les DIV-"res" jusqu'à ce que nous tombions sur une mention du domaine. Nous aurons ainsi le rang du domaine en question.La fonction clé: handle_starttag()
Le module de Python que nous allons utiliser est HTMLParser. Il dispose d'une méthode nommée handle_starttag().Fonctionnement
Cette méthode est appelée à chaque fois qu'un TAG ouvrant est rencontré. Il nous appartient de décider de ce qu'il faut faire TAG ouvrant par TAG ouvrant rencontré.Exemple
Si nous voulons extraire (et/ou afficher) les sources de toutes les images ainsi que les cibles de tous les liens d'une page fournie au parseur, alors voici une portion de code pour l'exemple (ce code n'est pas tout à fait juste, mais nous verrons plus tard sa forme définitive):def print_img_src(attrs):
print attrs['src']
def print_a_href(attrs):
print attrs['href']
def handle_starttag(tag, attrs):
if tag=='img':
print_img_src(dict(attrs))
elseif tag == 'a':
print_a_href(dict(attrs))
Le parseur: la classe
Pour avoir un code fonctionnel, nous devons aller plus loin dans les explications.Un parseur est chargé d'identifier certaines parties bien définies de ce qu'on lui donne. Le fait de "lui donner" quelquechose est obligatoire et s'appelle "to feed" en Anglais.
Une fois ces choses dites, observons la classe YahooParser et son utilisation à notre niveau.
Gestion des exceptions
Notre algorithme consiste à incrémenter un compteur à chaque fois qu'on rencontre un DIV dont la classe est "res". LE souci est que si on rencontre un DIV qui n'a pas d'attribut "class", alors le programme réagi par la levée d'une exception (et un arret). Il nous appartient de l'intercepter et de la gérer. Comme "gestion" nous proposons de passer notre chemin si il n'y a pas d'attribut. D'ou les lignes 17 et 18.Dictionnarisation (oups...)
handle_starttag() fourni "attrs" sous forme de liste de tuples. Nous avons besoin de transformer cela en dictionnaire, pour en simplifier le traitement. C'est ce que fait la fonction dict() dans le code.Précision sur le décompte implémenté
Dans handle_div(), nous incrémentons le compteur à chaque fois que nous rencontrons un DIV-"res".Dans handle_a(), nous affichons le rang (compteur) courant dès que nous rencontrons le nom de domaine recherché. Précison que le fait d'avoir "codé en dur" (hardcoded) le nom de domaine n'est pas ce qui se fait de plus propre, mais cela permet une meilleure compréhension du script.