Parser des fichiers HTML en Python

Ze amazing HTML cat (CC-BY Tomomi)
I can haz HTML (CC-BY Tomo­mi)

Lan­gage : Python
Biblio­thèques : bio­ser­vices, HTML­Par­ser, re (par­tiel­le­ment)
Niveau : débu­tant-inter­mé­diaire

Dans un article pré­cé­dent, je vous ai pré­sen­té le module bio­ser­vices en Python. Au cours de mon tra­vail j'ai été ame­née à récu­pé­rer des infor­ma­tions sur les termes Gene Onto­lo­gy, et notam­ment sur les rela­tions entre dif­fé­rents termes. Cepen­dant, les for­mats de fichiers récu­pé­rés sont dif­fé­rents en fonc­tion des don­nées qu'ils ren­ferment. Dans cet article, je vais vous pré­sen­ter com­ment récu­pé­rer dans un for­mat facile à lire les don­nées dans un fichier au for­mat HTML à par­tir de la biblio­thèque stan­dard HTML­Par­ser.

Récupérer les termes GO au format HTML

Dans un pre­mier temps, nous allons uti­li­ser le module bio­ser­vices pour récu­pé­rer les don­nées sur le terme GO:0003824, qui cor­res­pond à l'activité cata­ly­tique. Le for­mat deman­dé est le for­mat 'mini'.

Parser le fichier HTML récupéré

La ques­tion que l'on se pose main­te­nant est quelle sera la biblio­thèque Python à uti­li­ser pour par­ser le fichier récu­pé­ré. Dans la biblio­thèque stan­dard il existe un module per­met­tant de décou­per le for­mat HTML selon les balises et les attri­buts, voyons com­ment nous récu­pé­rons les don­nées de notre acti­vi­té cata­ly­tique.

Dans ce script, je crée la classe Base­Par­ser qui hérite de la classe HTML­Par­ser (du module du même nom). Puis je sur­charge les méthodes handle_​starttag, handle_​endtag et handle_​data.

La méthode handle_​starttag gère les ouver­tures de balises (ou tag) tag ain­si que leurs attri­buts (comme l'attribut href de la balise <a>) attrs.

La méthode handle_​endtag gère les fer­me­tures de balises tag.

La méthode handle_​data gère les don­nées data conte­nues entre les balises d'ouverture et de fer­me­ture.

Récupérer uniquement les fils de GO:0003824

Main­te­nant que l'on voit mieux com­ment fonc­tionne le module HTML­Par­ser, nous allons pou­voir sur­char­ger les méthodes à notre conve­nance afin de ne récu­pé­rer que les don­nées du tableau des fils.

Pour cela nous défi­nis­sions 3 variables boo­léennes : in_​td, in_​h2 et todo.

Si on ren­contre un tag d'ouverture h2, alors la variable in_​h2 vaut True. Si on ren­contre un tag de fer­me­ture h2, alors la variable in_​h2 vaut False.

Si, pen­dant que in_​h2 vaut True, les don­nées valent "Chil­dren", alors la variable todo vaut True.

Si on ren­contre un tag d'ouverture td, alors la variable in_​td vaut True. Si on ren­contre un tag de fer­me­ture td, alors la variable in_​td vaut False.

Lorsque l'on observe les don­nées, si les variables in_​td et todo valent toutes les deux True, alors on affiche les don­nées conte­nues entre les balises d'ouverture et de fer­me­ture de td.

Pour chaque don­nées lue, on sup­prime le retour à la ligne (\n) et on sup­prime l'espace en début de chaîne avec le module de mani­pu­la­tion d'expression régu­lière re.

 Conclusion

En conclu­sion je dirai qu'il n'est pas tou­jours néces­saire de cher­cher de gros modules très com­plets et com­plexes pour trai­ter cer­tains for­mats de fichiers, dans cet exemple vous pou­vez consta­ter que la biblio­thèque stan­dard de Python peut ample­ment suf­fire.

La rai­son prin­ci­pale pour laquelle je me suis pen­chée sur cette solu­tion réside dans le fait que l'on ne peut pas tou­jours ins­tal­ler des mille et des cents de modules ou de pro­grammes dans un envi­ron­ne­ment de tra­vail pro­fes­sion­nel. J'ai d'abord pré­fé­ré cher­cher dans les modules de base avant de deman­der à ce que l'on m'installe un module plus com­plet et com­plexe.


Mer­ci à Wocka, Yoann M. et ZaZo0o pour leur relec­ture et leurs com­men­taires.



Pour continuer la lecture :


Commentaires

4 réponses à “Parser des fichiers HTML en Python”

  1. Hel­lo,

    Tout d'abord mer­ci pour l'article qui est très clair sur la marche à suivre pour uti­li­ser HTML­Par­ser.
    Par contre, j'ai quelques cri­tiques à émettre.

    2 amé­lio­ra­tions pos­sibles sur le code écrit :
    — sup­pri­mer le exit() à la fin, il est inutile.
    — Pour­quoi lais­ser les variables 'qg' et 'term' en glo­bales ? Elles ont tout à fait leur place dans le main.
    C'est beau­coup plus propre et ca sera beau­coup plus facile de géné­ra­li­ser le script plus tard. 😉

    Enfin, j'ai beau­coup tiqué sur la conclu­sion qui est en par­tie fausse et en par­tie de mau­vaise foi. Je m'explique :
    Ce que tu dis (sur le fait d'installer pleins de paquets) est vrai pour pas mal de lan­gages (C++ par exemple) mais c'est en grande par­tie faux pour python.
    Python a un for­mi­dable outil de ges­tion de modules nom­mé 'pip' (qui est d'ailleurs stan­dard main­te­nant dans la 3.4). Cou­plé facul­ta­ti­ve­ment avec un vir­tua­lenv,
    tu peux ins­tal­ler toi-même tes modules dans ton HOME sans rien deman­der à per­sonne (avec l'option –user). Pip gère toutes les dépen­dances du modules et t'auras tou­jours la der­nière ver­sion (contrai­re­ment à un apt-get ou yum. D'ailleurs il ne fau­drait jamais gérer ses modules python avec ces ins­tal­leurs).
    Donc, la majo­ri­té du temps, tu pour­ras tou­jours ins­tal­ler mille et cents modules dans ton envi­ron­ne­ment de tra­vail pro­fes­sion­nel sans ne rien cas­ser ni deman­der à quelqu'un. C'est, ce que je trouve, une véri­table force de Python.
    La où je trouve qu'il y a un peu de mau­vaise foi, c'est lorsque tu dis "qu'il n'est pas néces­saire de cher­cher de gros modules très com­plets et com­plexes […]" or tu uti­lises le module bio­ser­vices qui est une véri­table usine 🙂 (11 dépen­dances d'après pip).
    D'ailleurs, dans ces dépen­dances, il y a "Beau­ti­ful­Soup" qui est un très bon par­ser de HTML. Pour­quoi ne pas l'avoir uti­li­ser ?

    1. Avatar de Nolwenn
      Nolwenn

      Bon­jour et mer­ci pour votre retour.

      Alors, pour com­men­cer, il est vrai que je ne l'ai pas pré­ci­sé dans l'article, mais dans mon uni­té, sur une ving­taine de per­sonnes, nous sommes 2 à coder en Python. Donc, ins­tal­ler Vir­tua­lEnv pour 2 per­sonnes, et qui n'ont aucune for­ma­tion des­sus, je n'en vois pas trop l'intérêt dans l'immédiat, il est pos­sible de s'en pas­ser.
      De plus, nous avons des HOME très res­treint en taille, ce qui fait que nous sommes très vite limi­té, donc Vir­tua­lEnv nous blo­que­rait rapi­de­ment pour ne serait-ce qu'un petit pro­jet 🙂 !

      Pour Beau­ti­ful­Soup, j'avoue que je l'ignorais, mer­ci de m'en infor­mer, je ne l'ai pas vu pas­ser dans la liste des dépen­dances, pip gérant l'installation comme un grand, dépen­dances com­prises, je n'ai pas prê­té grande atten­tion lorsque j'avais tes­té Bio­ser­vices sur une machine vir­tuelle 🙂 ! Ce qui explique pour­quoi je ne l'ai pas uti­li­sé. En revanche, je l'ai décou­vert après en vou­lant mani­pu­ler des don­nées retour­nées dans une classe de Beau­ti­ful­Soup (après avoir cher­ché à com­prendre la classe en ques­tion).

      Pour finir, l'objectif de ce billet était de pré­sen­ter HTML­Par­ser, je l'ai fait en uti­li­sant des don­nées retour­nées grâce à Bio­ser­vices, tout comme j'aurais pu le faire avec une page de La Poste 🙂 !

      Donc, pour la mau­vaise foi, un peu mais pas trop 🙂 !

      Bonne jour­née et encore mer­ci pour votre retour.

      1. On est d'accord qu'on peut très bien se pas­ser de l'utilisation de vir­tua­lenv. Ca apporte juste une sur­couche pour gérer dif­fé­rentes ver­sions de modules.
        Par contre, rien n'empêche d'installer des modules loca­le­ment via pip ailleurs que dans le HOME 😉

  2. HTML­Par­ser est inté­res­sant.

    Mais il y a en effet Beau­ti­ful­Soup et aus­si lxml sur­tout com­bi­né avec html5lib. Par exemple

    from bs4 import Beau­ti­ful­Soup
    html­file = urllib2.urlopen(uri)
    soup = BeautifulSoup(htmlfile, "html5lib")
    list = soup.find(class_='toto')

    ou bien

    from lxml.html import html5parser
    HTMLNS = "http://​www​.w3​.org/​1​9​9​9​/​x​h​tml"
    parsed_​html = html5parser.parse(uri)
    title = parsed_html.xpath('//h:title', namespaces={'h': HTMLNS})[0].text

Laisser un commentaire