Langage : Python
Bibliothèques : bioservices, HTMLParser, re (partiellement)
Niveau : débutant-intermédiaire
Dans un article précédent, je vous ai présenté le module bioservices en Python. Au cours de mon travail j'ai été amenée à récupérer des informations sur les termes Gene Ontology, et notamment sur les relations entre différents termes. Cependant, les formats de fichiers récupérés sont différents en fonction des données qu'ils renferment. Dans cet article, je vais vous présenter comment récupérer dans un format facile à lire les données dans un fichier au format HTML à partir de la bibliothèque standard HTMLParser.
Récupérer les termes GO au format HTML
Dans un premier temps, nous allons utiliser le module bioservices pour récupérer les données sur le terme GO:0003824, qui correspond à l'activité catalytique. Le format demandé est le format 'mini'.
1 2 3 4 5 6 7 8 |
#!/usr/bin/env python from bioservices import QuickGO qg = QuickGO() term = qg.Term("GO:0003824", format="mini") print term |
Parser le fichier HTML récupéré
La question que l'on se pose maintenant est quelle sera la bibliothèque Python à utiliser pour parser le fichier récupéré. Dans la bibliothèque standard il existe un module permettant de découper le format HTML selon les balises et les attributs, voyons comment nous récupérons les données de notre activité catalytique.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
#!/usr/bin/env python from bioservices import QuickGO from HTMLParser import HTMLParser qg = QuickGO() term = qg.Term("GO:0003824", format="mini") class BaseParser(HTMLParser): def handle_starttag(self, tag, attrs): print "start tag:",tag print "attributes:",attrs def handle_endtag(self, tag): print "end tag:",tag def handle_data(self, data): print "data:",data if __name__ == "__main__": p = BaseParser() p.feed(term) exit() |
Dans ce script, je crée la classe BaseParser qui hérite de la classe HTMLParser (du module du même nom). Puis je surcharge les méthodes handle_starttag, handle_endtag et handle_data.
La méthode handle_starttag gère les ouvertures de balises (ou tag) tag ainsi que leurs attributs (comme l'attribut href de la balise <a>) attrs.
La méthode handle_endtag gère les fermetures de balises tag.
La méthode handle_data gère les données data contenues entre les balises d'ouverture et de fermeture.
Récupérer uniquement les fils de GO:0003824
Maintenant que l'on voit mieux comment fonctionne le module HTMLParser, nous allons pouvoir surcharger les méthodes à notre convenance afin de ne récupérer que les données du tableau des fils.
Pour cela nous définissions 3 variables booléennes : in_td, in_h2 et todo.
Si on rencontre un tag d'ouverture h2, alors la variable in_h2 vaut True. Si on rencontre un tag de fermeture h2, alors la variable in_h2 vaut False.
Si, pendant que in_h2 vaut True, les données valent "Children", alors la variable todo vaut True.
Si on rencontre un tag d'ouverture td, alors la variable in_td vaut True. Si on rencontre un tag de fermeture td, alors la variable in_td vaut False.
Lorsque l'on observe les données, si les variables in_td et todo valent toutes les deux True, alors on affiche les données contenues entre les balises d'ouverture et de fermeture de td.
Pour chaque données lue, on supprime le retour à la ligne (\n) et on supprime l'espace en début de chaîne avec le module de manipulation d'expression régulière re.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
#!/usr/bin/env python from bioservices import QuickGO from HTMLParser import HTMLParser import re qg = QuickGO() term = qg.Term("GO:0003824", format="mini") class Parser(HTMLParser): def __init__(self): HTMLParser.__init__(self) self.in_td = False self.in_h2 = False self.todo = False def handle_starttag(self, tag, attrs): if tag == 'h2': self.in_h2 = True if tag == 'td': self.in_td = True def handle_endtag(self, tag): if tag == 'td': self.in_td = False if tag == 'h2': self.in_h2 = False def handle_data(self, data): if self.in_h2 : if data == "Children": self.todo = True if data != "Children": self.todo = False if self.todo and self.in_td : data = re.sub(r'\n', '', data) data = re.sub(r'^ ', '', data) if data != "": print data if __name__ == "__main__": p = Parser() p.feed(term) exit() |
Conclusion
En conclusion je dirai qu'il n'est pas toujours nécessaire de chercher de gros modules très complets et complexes pour traiter certains formats de fichiers, dans cet exemple vous pouvez constater que la bibliothèque standard de Python peut amplement suffire.
La raison principale pour laquelle je me suis penchée sur cette solution réside dans le fait que l'on ne peut pas toujours installer des mille et des cents de modules ou de programmes dans un environnement de travail professionnel. J'ai d'abord préféré chercher dans les modules de base avant de demander à ce que l'on m'installe un module plus complet et complexe.
Merci à Wocka, Yoann M. et ZaZo0o pour leur relecture et leurs commentaires.
Laisser un commentaire