2017-05-09 2 views
2

J'essaie de convertir une page HTML en une arborescence. J'ai tiré cette classe (j'ai enlevé ce que je fais en fait avec chaque balise car il est pas pertinent):Comment gérer un élément HTML vide sans la barre oblique?

class PageParser(html.parser.HTMLParser): 
    def handle_starttag(self, tag, attrs): 
     print("start "+tag) 
    def handle_endtag(self, tag): 
     print("end "+tag) 
    def handle_startendtag(self, tag, attrs): 
     print("startend "+tag) 

Je me attendais éléments vides pour déclencher la méthode handle_startendtag. Le problème est que lorsque vous rencontrez un élément vide comme <meta>, seule la méthode handle_starttag est appelée. La balise est jamais fermée de ma classe point de vue:

parser = PageParser() 
parser.feed('<div> <meta charset="utf-8"> </div>') 

impressions:

start div 
start meta 
end div 

je dois savoir quand chaque élément a été fermé pour créer correctement l'arbre. Comment puis-je savoir si un tag est un élément vide?

+2

De les docs: _ "Cet analyseur ne vérifie pas que les balises de fin correspondent aux balises de début ou d'appel le gestionnaire de balise de fin pour les éléments qui sont fermés implicitement en fermant un élément externe. "_ https://docs.python.org/3/library/html.parser.html – Hamish

+0

Vous devez entrer le code XML strict où le' 'tag n'est plus valide et vous devez l'écrire comme' 'ou garder une trace d'une liste d'étiquettes qui pourraient venir comme des étiquettes vides, comme les'
'ou les' 'tags. –

+1

http://stackoverflow.com/questions/3115448/best-way-to-convert-the-this-html-file-into-an-xml-file-using-python –

Répondre

2

Vérification du documentation, et plus précisément cet exemple:

Parsing un élément avec quelques attributs et un titre:

>>>parser.feed('<img src="python-logo.png" alt="The Python logo">') 
Start tag: img 
    attr: ('src', 'python-logo.png') 
    attr: ('alt', 'The Python logo') 

Nous pouvons déterminer que c'est le comportement attendu.

La meilleure suggestion vient du commentaire @HenryHeath: Utilisez BeautifulSoup.

Si vous ne voulez pas l'utiliser si, vous pouvez travailler autour du comportement attendu de HTMLParser comme suit:

  • Ceci est une liste de tous les HTML 5.2 void element.
  • Créer une liste avec les noms d'éléments:

    void_elements = ['area', 'base', ... , 'wbr'] 
    
  • En handle_starttag vérifier si la balise est dans la liste void_elements:

    class PageParser(html.parser.HTMLParser): 
        def handle_starttag(self, tag, attrs): 
         if tag in void_elements: 
          # DO what should happen inside handle_startendtag() 
          print("void element "+tag) 
         else: 
          print("start "+tag) 
    

Bonne chance :)

+1

Votre solution a fonctionné, merci. En analysant une page Twitter, j'ai trouvé qu'ils utilisent la balise 'link' comme un élément vide, mais ce n'est pas dans la liste que vous avez liée.Je ne sais pas si c'est le cas (peut-être que ce n'est pas standard), mais je l'ai mis là au cas où quelqu'un rencontrerait le même problème. – Arno