2010-01-02 5 views
4

Lors de l'utilisation de la classe HTMLParser en Python, est-il possible d'abandonner le traitement dans une fonction handle_*? Au début du traitement, j'obtiens toutes les données dont j'ai besoin, ce qui me semble une perte de continuer à traiter. Voici un exemple d'extraction de la description de méta pour un document.Abandonner le traitement HTMLParser en Python

from HTMLParser import HTMLParser 

class MyParser(HTMLParser): 

    def handle_start(self, tag, attrs): 
     in_meta = False 
     if tag == 'meta': 
      for attr in attrs: 
       if attr[0].lower() == 'name' and attr[1].lower() == 'description': 
        in_meta = True 
       if attr[0].lower() == 'content': 
        print(attr[1]) 
        # Would like to tell the parser to stop now, 
        # since I have all the data that I need 
+2

ne devriez-vous pas hériter HTMLParser et pas Parser? –

+1

Oh, et je recommande vraiment BeautifulSoup pour l'analyse HTML - il est beaucoup plus facile à utiliser –

+0

Je pense qu'il est facile de parvenir à une conclusion, qu'il s'agit simplement d'une faute de frappe. Parce que si ce n'était pas ce code ne fonctionnerait pas. – shylent

Répondre

9

Vous pouvez soulever une exception et envelopper votre .feed() appel dans un bloc try.

Vous pouvez également appeler self.reset() lorsque vous décidez que vous avez terminé (je ne l'ai pas vraiment essayé, mais selon documentation « Réinitialiser l'instance Perd toutes les données non traitées. »., - ce qui est précisément ce dont vous avez besoin).

+3

Une exception ne semble pas être une bonne idée ici - les exceptions ne devraient être utilisées que pour des conditions exceptionnelles, et dans ce cas vous venez de le proposer pour être utilisé comme un outil de contrôle-flux. Pour ce qui est de la méthode 'reset', je l'ai aussi envisagé mais je ne sais pas si c'est vraiment pertinent ici: –

+5

re: "exceptions .. pour des conditions exceptionnelles" - pas si vrai pour python. Savez-vous que StopIteration est déclenché chaque fois qu'un itérateur "n'a plus d'itérations"? Ce n'est pas vraiment une "condition exceptionnelle", n'est-ce pas? En fait, il est distinctement similaire à la condition, que le questionneur veut gérer, - une sorte de "pause maintenant". – shylent

+2

@shylent: true à propos de StopIteration, mais cela est rarement géré manuellement, mais plutôt enveloppé de sorte que l'utilisateur ne le voit presque jamais directement. Néanmoins, vous faites un bon point. –

1

Si vous utilisez la méthode scanString de pyparsing, vous avez plus de contrôle sur la longueur de la chaîne d'entrée. Dans notre exemple, nous créons une expression qui correspond à une balise <meta> et ajoute une action d'analyse qui garantit que nous ne faisons correspondre la balise qu'avec name="description". Ce code suppose que vous avez lu de code HTML dans la variable htmlsrc la page: L'extension sur @ réponse de shylent, voici ma solution

from pyparsing import makeHTMLTags, withAttribute 

# makeHTMLTags creates both open and closing tags, only care about the open tag 
metaTag = makeHTMLTags("meta")[0] 
metaTag.setParseAction(withAttribute(name="description")) 

try: 
    # scanString is a generator that returns each match as it is found 
    # in the input 
    tokens,startloc,endloc = metaTag.scanString(htmlsrc).next() 

    # attributes can be accessed like object attributes if they are 
    # valid Python names 
    print tokens.content 

    # if the attribute name clashes with a Python keyword, or is 
    # otherwise unsuitable as an identifier, use dict-like access instead 
    print tokens["content"] 

except StopIteration: 
    print "no matching meta tag found" 
+2

Merci pour la réponse. Je suis sûr que cela fonctionne aussi bien et j'apprécie avoir une certaine introduction à pyparsing. Je marquerais les deux correctes si je pouvais. –

0

:

class MyParser(HTMLParser): 

    boolean_flag = False 

    def handle_starttag(self, tag, attrs): 
     # for example: 
     self.boolean_flag = (tag == "sometag" and ("id", "someid") in attrs) 

    def handle_endtag(self, tag): 
     pass 

    def handle_data(self, data): 
     if self.boolean_flag: 
      raise DataParsedException(data) 


class DataParsedException(Exception): 
    def __init__(self, data): 
     self.data = data 

Utilisation:

try: 
    parser.feed(html.decode()) 
except DataParsedException as dataParsed: 
    vars.append(dataParsed.data) 

Il ne le travail.

Questions connexes