2010-07-02 29 views
1

J'utilise BeautifulSoup pour faire du scrap. Mon problème est le suivant: J'ai besoin d'extraire des choses spécifiques d'un paragraphe. Un exemple:Comment utiliser BeautifulSoup pour extraire d'un paragraphe HTML?

<p><b><a href="/name/abe">ABE</a></b> &nbsp; <font class="masc">m</font> &nbsp; <font class="info"><a href="/nmc/eng.php" class="usg">English</a>, <a href="/nmc/jew.php" class="usg">Hebrew</a></font><br />Short form of <a href="/name/abraham" class="nl">ABRAHAM</a> 

Sur ce point, je suis en mesure d'extraire le nom ABE comme suit:

for pFound in soup.findAll('p'): 

    print pFound 


#will get the names 
    x = pFound.find('a').renderContents() 
    print x 

Maintenant, mon problème est d'extraire l'autre nom et, dans le même paragraphe .

Short form of <a href="/name/abraham" class="nl">ABRAHAM</a> 

Je dois extraire uniquement si la balise a est précédé du texte « expurgée de »

Toutes les idées sur la façon de le faire? Il y a beaucoup de tels paragraphes dans la page HTML, et tous n'ont pas le texte "Forme courte de" Ils peuvent contenir un autre texte à cet endroit.

Je pense qu'une combinaison de regex et findNext() peut être utile, mais je ne connais pas BeautifulSoup. Fini par perdre beaucoup de temps.

Toute aide serait appréciée. Merci.

Répondre

1

Ce qui suit devrait fonctionner ...:

htm = '''<p><b><a href="/name/abe">ABE</a></b> &nbsp; <font class="masc">m 
</font>&nbsp; <font class="info"><a href="/nmc/eng.php" class="usg">English 
</a>, <a href="/nmc/jew.php" class="usg">Hebrew</a></font><br /> 
Short form of <a href="/name/abraham" class="nl">ABRAHAM</a>''' 

import BeautifulSoup 

soup = BeautifulSoup.BeautifulSoup(htm) 

for p in soup.findAll('p'): 
    firsta = True 
    shortf = False 
    for c in p.recursiveChildGenerator(): 
    if isinstance(c, BeautifulSoup.NavigableString): 
     if 'Short form of' in str(c): 
     shortf = True 
    elif c.name == 'a': 
     if firsta or shortf: 
     print c.renderContents() 
     firsta = shortf = False 
+0

Merci Alex, qui a travaillé avec quelques modifications. –

+0

@kartiku, de rien, et, heureux d'entendre cela! –

0

Vous pouvez utiliser pyparsing comme une sorte de "super-regex" pour l'analyse syntaxique par HTML. Vous pouvez assembler un modèle de correspondance simple en assemblant les différentes balises de début et de fin, sans trébucher sur les pièges de grattage HTML typiques (balise imprévisible de balise/attribut, attributs imprévisibles, attributs en désordre, espaces imprévisibles). Ensuite, pattern.scanString renverra un générateur qui balaiera la source HTML et retournera les tuples des jetons correspondants, les emplacements de début et de fin. Jetez dans l'attribution des noms de résultats (similaire aux champs nommés dans regex), et l'accès aux champs d'intérêt individuels est simple.

html = """<some leading html> 
<p><b><a href="/name/abe">ABE</a></b> &nbsp; <font class="masc">m</font> &nbsp; 
<font class="info"><a href="/nmc/eng.php" class="usg">English</a>, <a href="/nmc/jew.php" class="usg"> 
Hebrew</a></font><br />Short form of <a href="/name/abraham" class="nl">ABRAHAM</a> 
<some trailing html>""" 

from pyparsing import makeHTMLTags, SkipTo, Optional 

pTag,pEnd = makeHTMLTags("P") 
bTag,bEnd = makeHTMLTags("B") 
aTag,aEnd = makeHTMLTags("A") 
fontTag,fontEnd = makeHTMLTags("FONT") 
brTag = makeHTMLTags("BR")[0] 
nbsp = "&nbsp;" 

nickEntry = (pTag + bTag + aTag + SkipTo(aEnd)("nickname") + aEnd + bEnd + Optional(nbsp) + 
      fontTag + SkipTo(fontEnd) + fontEnd + Optional(nbsp) + 
      fontTag + aTag + SkipTo(aEnd) + aEnd + "," + 
      aTag + SkipTo(aEnd) + aEnd + fontEnd + 
      brTag + "Short form of" + 
      aTag + SkipTo(aEnd)("fullname") + aEnd) 

for match,_,_ in nickEntry.scanString(html): 
    print match.nickname, "->", match.fullname 

impressions:

ABE -> ABRAHAM