[Python] HTML parsing

Fermé
dje-dje Messages postés 10415 Date d'inscription mardi 6 janvier 2004 Statut Modérateur Dernière intervention 28 janvier 2011 - 8 avril 2004 à 15:20
sebsauvage Messages postés 32893 Date d'inscription mercredi 29 août 2001 Statut Modérateur Dernière intervention 21 octobre 2019 - 6 févr. 2005 à 12:42
Bonjour,
Cette fois j'ai un soucis pour récupérer les données contenues entre 2 tag que j'ai bien identifié.
Disons qu'avec handle_starttag, je vois clairement le nombre de tag dont je cherche à choper le contenu. Avec handle_data, je récupère le contenu de tous les tag.
Comment préciser à handle_data qu'il ne doit agir que si les éléments identifiant le tag que je cherche sont trouvés ? (Ou comment dire à handle_starttag de me renvoyé les data qui suivent, même si je préférerais la première solution)
Merci

a+
dje-dje

Il y a 10 types de personne dans le monde,
ceux qui comprennent le binaire et les autres
A voir également:

13 réponses

sebsauvage Messages postés 32893 Date d'inscription mercredi 29 août 2001 Statut Modérateur Dernière intervention 21 octobre 2019 15 655
26 avril 2004 à 16:48
Une expression régulière pourrait suffire, je pense.
Ou même sans. Un simple .find() pourrait faire l'affaire.

Petit exemple avec find:
# -*- coding: iso-8859-1 -*-

# Nos données à tester:
data = """aaaa<!-- Begin : Toto -->bbb<!-- End : Toto est OK -->ccc
<!-- Begin : Toto --> Encore un autre !  dddd<!-- End : Toto est OK -->"""

beginTag = "<!-- Begin : Toto -->"
endTag   = "<!-- End : Toto est OK -->"

startPos = data.find(beginTag)

while startPos > -1:
    endPos = data.find(endTag,startPos+1)
    if endTag == -1:
      break
    else:
      print "Trouvé:",data[startPos+len(beginTag):endPos]
      startPos = data.find(beginTag,endPos+1)


Ce programme va afficher:
Trouvé: bbb
Trouvé:  Encore un autre !  dddd



A cause de la façon dont est implémenté .find(), ce bout de code est plus rapide que les expressions régulière, et aussi plus rapide que l'utilisation d'un parseur (SGMLParser ou HTMLParser).

Mais bien sûr rien ne t'empêche d'utiliser HTMLParser: tu peux récupérer les commentaires par la méthode handle_comment(data).
2
Salut,

Dis moi, au sujet du parsing html, j'aimerais le faire mais pour une URL. Est-ce possible ?
0
sebsauvage Messages postés 32893 Date d'inscription mercredi 29 août 2001 Statut Modérateur Dernière intervention 21 octobre 2019 15 655 > Christophe
6 févr. 2005 à 12:42
oui bien sur:

import urllib
monurl = "http://sebsauvage.net/index.html"
monhtml = urllib.urlopen(monurl).read()


et voilà !
0
sebsauvage Messages postés 32893 Date d'inscription mercredi 29 août 2001 Statut Modérateur Dernière intervention 21 octobre 2019 15 655
8 avril 2004 à 15:44
Il faut utiliser handle_data().

Prend mon programme http://sebsauvage.net/python/html2csv.py
C'est un exemple d'utilisation de HTMLParser:
ça convertis tous les tableaux HTML trouvés en un fichier CSV (pour chargement dans Excel).

Le truc est d'avoir un flag (booléen) qui t'indique si tu es à l'intérieur du tag ou non.
handle_starttag() mettra ce flag à vrai.
handle_endtag() mettra ce flag à faux.
handle_data() ne gardera les données que si le flag est à vrai.

(dans mon programme, j'ai plusieurs flags : inTD (suis-je dans un tag TD ?), inTR, etc.)

Le pseudo-code serait:
class monparseur:
  def __init__():
    self.inMONTAG = false
  def handle_starttag():
    Si tag=="MONTAG": self.inMONTAG=true
  def handle_endttag():
    Si tag=="MONTAG": self.inMONTAG=false
  def handle_data():
    Si self.inMONTAG==true: affiche "J'ai trouvé un tag <MONTAG> contenant:",data


Note que HTMLParser n'est que l'une des nombreuses manière de parser du HTML.
Tu pourrais aussi passer par d'autres API comme DOM ou SAX (je ne maîtrise pas, et ça nécessite l'installation de librairies supplémentaires.)
Il existe plusieurs librairies différentes pour DOM et SAX, plus ou moins grosses... euh complexes je voulais dire.
0
dje-dje Messages postés 10415 Date d'inscription mardi 6 janvier 2004 Statut Modérateur Dernière intervention 28 janvier 2011 757
8 avril 2004 à 16:07
J'y avaisi pensé mais ça n'a pas fonctionné. (J'avais mis le flag en variable globale et pas comme donnée de la classe comme tu sembles le préconiser)

En faisant comme tu dis, j'ai une erreur, sans doute lié à ma méconnaissance (encore!) de la fonction __init__

Je te mets mon code pour que tu me dise ce qui va pas:
class MyHTMLParser(HTMLParser):
def __init__():
self.InMonTag = 0

def handle_data(self,data):
if InMonTag==1:
print data

def handle_starttag(self, tag, attrs): # j'utilise les attributs
if tag == 'CeQueJeVeux':
self.InMonTag = 1

p = MyHTMLParser()
file = open('MonFichier','r')
chaine = file.read()
p.feed(chaine)
p.close()

Et il m'insulte avec ça:
p = MyHTMLParser()
TypeError: __init__() takes no arguments (1 given)

a+
dje-dje
Merci de ton aide


Il y a 10 types de personne dans le monde,
ceux qui comprennent le binaire et les autres
0
sebsauvage Messages postés 32893 Date d'inscription mercredi 29 août 2001 Statut Modérateur Dernière intervention 21 octobre 2019 15 655
8 avril 2004 à 16:31
Ah... __init__().

Il faut que tu jette un coup d'oeil du côté programmation objet en Python.

__init__(self) est le constructeur.
Il est appelé quand la classe est créée.
Il doit être toujours déclaré avec au minimum 1 argument:
def __init__(self):

self.InMonTag=0 sert à créer une variable local à l'objet (spécifique à cet objet). (Aussi appelé "attribut" de l'objet.)


Attention: dans ton handle_data(), tu a utilisé InMonTag, qui est une variable locale à la fonction handle_data(). C'est donc une variable différente de self.InMonTag !

Il faut mettre explicitement self.InMonTag pour se référer à la variable déclarée dans le constructeur.
--> je te suggère de lire ce qui concerne le scope des objets en Python.

:-)
Si tu as des questions, n'hésite pas !


PS: Je ne me connecterai probablement de demain (vendredi) jusqu'à lundi. Je ne serai donc de retour que mardi.
0
dje-dje Messages postés 10415 Date d'inscription mardi 6 janvier 2004 Statut Modérateur Dernière intervention 28 janvier 2011 757
8 avril 2004 à 16:37
Ok, j'ai déjà fait de l'objet mais en C++, donc je suis familié des concept d'attribut (ou donnée membre), mais la syntaxe me laisse encore perplexe.
Encore merci et Bon (et Gros dis donc!) Week-end!

a+
dje-dje

Il y a 10 types de personne dans le monde,
ceux qui comprennent le binaire et les autres
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
dje-dje Messages postés 10415 Date d'inscription mardi 6 janvier 2004 Statut Modérateur Dernière intervention 28 janvier 2011 757
8 avril 2004 à 16:41
Zut, j'ai rajouté le self dans la définition du __init__ et maintenant, j'ai ça:
self.rawdata = self.rawdata + data
AttributeError: MyHTMLParser instance has no attribute 'rawdata'

Je vais lire un peu de Doc moi ;-)

a+

Il y a 10 types de personne dans le monde,
ceux qui comprennent le binaire et les autres
0
sebsauvage Messages postés 32893 Date d'inscription mercredi 29 août 2001 Statut Modérateur Dernière intervention 21 octobre 2019 15 655
8 avril 2004 à 17:07
Il faut déclarer ton self.rawdata dans ton constructeur.
(Même si c'est pour mettre None dedans).

self.rawdata = None
0
dje-dje Messages postés 10415 Date d'inscription mardi 6 janvier 2004 Statut Modérateur Dernière intervention 28 janvier 2011 757
8 avril 2004 à 17:07
J'ai changé 2 trucs:
(En m'inspirant méchamment de ton code ;-) )

import HTMLParser (au lieu de import HTMLParser from HTMLParser)

et

def __init__(self):
HTMLParser.HTMLParser.__init__(self)
self.InMonTag = 0
(au lieu de la précédente)

ca marche, mais j'ai fait quoi?

a+
dje-dje
En tout cas merci

Il y a 10 types de personne dans le monde,
ceux qui comprennent le binaire et les autres
0
dje-dje Messages postés 10415 Date d'inscription mardi 6 janvier 2004 Statut Modérateur Dernière intervention 28 janvier 2011 757
15 avril 2004 à 11:53
Si tu pouvais répondre à ma question du message <6> (t'as pas du la voir, il a été posté en même temps que ton <7>)

a+
dje-dje

Il y a 10 types de personne dans le monde,
ceux qui comprennent le binaire et les autres
0
sebsauvage Messages postés 32893 Date d'inscription mercredi 29 août 2001 Statut Modérateur Dernière intervention 21 octobre 2019 15 655
15 avril 2004 à 12:03
Ah... il faut toujours impérativement appeler le constructeur de la classe mère, sinon ton objet n'est pas dans un état correct.

(C'est le HTMLParser.HTMLParser.__init__(self) que tu as fait.)
0
dje-dje Messages postés 10415 Date d'inscription mardi 6 janvier 2004 Statut Modérateur Dernière intervention 28 janvier 2011 757
15 avril 2004 à 12:13
Ok...


Mon objectif est d'aspirer le site des pages jaunes pour des sections que j'ai choisi. (Avec mon parser, j'essaie de virer ce qui n'est pas intéressant:pub,blabla,...)

En fait, je comptais utiliser urllib en m'inspirant - encore - de ton code, mais l'url ne change pas: c'est toujours le même script cgi qui est appelé et ils ne passent aucun paramètres dans l'url

Penses-tu que c'est possible de réaliser cet aspirateur de pages jaunes en python?

a+
dje-dje

Il y a 10 types de personne dans le monde,
ceux qui comprennent le binaire et les autres
0
dje-dje Messages postés 10415 Date d'inscription mardi 6 janvier 2004 Statut Modérateur Dernière intervention 28 janvier 2011 757
23 avril 2004 à 15:46
Up!

a+
dje-dje

Il y a 10 types de personne dans le monde,
ceux qui comprennent le binaire et les autres
0
sebsauvage Messages postés 32893 Date d'inscription mercredi 29 août 2001 Statut Modérateur Dernière intervention 21 octobre 2019 15 655
23 avril 2004 à 18:33
c'est toujours le même script cgi qui est appelé et ils ne passent aucun paramètres dans l'url

Penses-tu que c'est possible de réaliser cet aspirateur de pages jaunes en python?


C'est parceque ce sont des requêtes en mode POST.
On peut parfaitement en faire en Python, aucun problème.

Ton projet est tout à fait réalisable en Python.
0
dje-dje Messages postés 10415 Date d'inscription mardi 6 janvier 2004 Statut Modérateur Dernière intervention 28 janvier 2011 757
26 avril 2004 à 09:25
Ok, merci beaucoup!

a+
dje-dje

Il y a 10 types de personne dans le monde,
ceux qui comprennent le binaire et les autres
0
Je souhaite réaliser le même principe mais cette fois entre 2 balises !!!

Je m'explique :

J'ai une page HTML venant grace à urllib,
Je veux récupérer le texte entre 2 balises
<!-- Begin : Toto --> et <!-- End : Toto est OK -->

Je n'arrive pas à voir comment faire !!
help me please !
0