web-dev-qa-db-fra.com

Utilisation de BeautifulSoup pour trouver une balise HTML contenant du texte

J'essaie d'obtenir les éléments d'un document HTML qui contiennent le modèle de texte suivant: #\S {11}

<h2> this is cool #12345678901 </h2>

Ainsi, le précédent correspondrait en utilisant:

soup('h2',text=re.compile(r' #\S{11}'))

Et les résultats seraient quelque chose comme:

[u'blahblah #223409823523', u'thisisinteresting #293845023984']

Je peux obtenir tout le texte qui correspond (voir la ligne ci-dessus). Mais je veux que l'élément parent du texte corresponde, donc je peux l'utiliser comme point de départ pour parcourir l'arborescence du document. Dans ce cas, je voudrais que tous les éléments h2 retournent, pas les correspondances de texte.

Des idées?

60
sotangochips
from BeautifulSoup import BeautifulSoup
import re

html_text = """
<h2>this is cool #12345678901</h2>
<h2>this is nothing</h2>
<h1>foo #126666678901</h1>
<h2>this is interesting #126666678901</h2>
<h2>this is blah #124445678901</h2>
"""

soup = BeautifulSoup(html_text)


for elem in soup(text=re.compile(r' #\S{11}')):
    print elem.parent

Tirages:

<h2>this is cool #12345678901</h2>
<h2>this is interesting #126666678901</h2>
<h2>this is blah #124445678901</h2>
69
nosklo

Les opérations de recherche de BeautifulSoup fournissent [une liste de] BeautifulSoup.NavigableString objets lorsque text= est utilisé comme critère par opposition à BeautifulSoup.Tag dans d'autres cas. Vérifiez le __dict__ pour voir les attributs mis à votre disposition. Parmi ces attributs, parent est préféré à previous à cause de changements dans BS4 .

from BeautifulSoup import BeautifulSoup
from pprint import pprint
import re

html_text = """
<h2>this is cool #12345678901</h2>
<h2>this is nothing</h2>
<h2>this is interesting #126666678901</h2>
<h2>this is blah #124445678901</h2>
"""

soup = BeautifulSoup(html_text)

# Even though the OP was not looking for 'cool', it's more understandable to work with item zero.
pattern = re.compile(r'cool')

pprint(soup.find(text=pattern).__dict__)
#>> {'next': u'\n',
#>>  'nextSibling': None,
#>>  'parent': <h2>this is cool #12345678901</h2>,
#>>  'previous': <h2>this is cool #12345678901</h2>,
#>>  'previousSibling': None}

print soup.find('h2')
#>> <h2>this is cool #12345678901</h2>
print soup.find('h2', text=pattern)
#>> this is cool #12345678901
print soup.find('h2', text=pattern).parent
#>> <h2>this is cool #12345678901</h2>
print soup.find('h2', text=pattern) == soup.find('h2')
#>> False
print soup.find('h2', text=pattern) == soup.find('h2').text
#>> True
print soup.find('h2', text=pattern).parent == soup.find('h2')
#>> True
19
Bruno Bronosky

Avec bs4 (Beautiful Soup 4), la tentative du PO fonctionne exactement comme prévu:

from bs4 import BeautifulSoup
soup = BeautifulSoup("<h2> this is cool #12345678901 </h2>")
soup('h2',text=re.compile(r' #\S{11}'))

résultats [<h2> this is cool #12345678901 </h2>].

2
T.C. Proctor