2012-08-04 11 views
5
html = """ 
... 
<tt class="descname">all</tt> 
<big>(</big> 
<em>iterable</em> 
<big>)</big> 
<a class="headerlink" href="#all" title="Permalink to this definition">¶</a> 
... 
""" 

Quiero obtener todo el texto entre la etiqueta de inicio big hasta antes de la primera aparición de la etiqueta a. Esto significa que si tomo este ejemplo, entonces debo obtener (iterable) como una cadena.¿Cómo obtener todo el texto entre solo dos etiquetas específicas usando BeautifulSoup?

Respuesta

3

evitaría nextSibling, a partir de su pregunta, desea incluir todo hasta el siguiente <a>, independientemente de si se trata de un elemento hermano, principal o secundario.

Por lo tanto, creo que el mejor enfoque es encontrar el nodo que es el siguiente elemento y bucle de <a> recursivamente hasta entonces, agregando cada cadena como se encuentra. Es posible que tenga que poner en orden el siguiente código HTML si es muy diferente de la muestra, pero algo como esto debería funcionar:

from bs4 import BeautifulSoup 
#by taking the `html` variable from the question. 
html = BeautifulSoup(html) 
firstBigTag = html.find_all('big')[0] 
nextATag = firstBigTag.find_next('a') 
def loopUntilA(text, firstElement): 
    text += firstElement.string 
    if (firstElement.next.next == nextATag):    
     return text 
    else: 
     #Using double next to skip the string nodes themselves 
     return loopUntilA(text, firstElement.next.next) 
targetString = loopUntilA('', firstBigTag) 
print targetString 
+0

sí, exactamente, quiero incluir todo hasta la próxima etiqueta 'a' y puede haber cualquier cantidad de etiquetas, textos entre la primera etiqueta 'grande' y la primera etiqueta 'a' –

0
>>> from BeautifulSoup import BeautifulSoup as bs 
>>> parsed = bs(html) 
>>> txt = [] 
>>> for i in parsed.findAll('big'): 
...  txt.append(i.text) 
...  if i.nextSibling.name != u'a': 
...   txt.append(i.nextSibling.text) 
... 
>>> ''.join(txt) 
u'(iterable)' 
+0

'nextiSbling' no puede ser utilizado como quiero incluir todos los textos hasta la primera aparición de la etiqueta 'a' –

1

se puede hacer así:

from BeautifulSoup import BeautifulSoup 
html = """ 
<tt class="descname">all</tt> 
<big>(</big> 
<em>iterable</em> 
<big>)</big> 
<a class="headerlink" href="test" title="Permalink to this definition"></a> 
""" 
soup = BeautifulSoup(html) 
print soup.find('big').nextSibling.next.text 

Para información Comprobar dom atravesar con BeautifulSoup de here

+0

Esto devuelve "iterable" en lugar de "(iterable)" – anotherdave

5

un enfoque iterativo.

from BeautifulSoup import BeautifulSoup as bs 
from itertools import takewhile, chain 

def get_text(html, from_tag, until_tag): 
    soup = bs(html) 
    for big in soup(from_tag): 
     until = big.findNext(until_tag) 
     strings = (node for node in big.nextSiblingGenerator() if getattr(node, 'text', '').strip()) 
     selected = takewhile(lambda node: node != until, strings) 
     try: 
      yield ''.join(getattr(node, 'text', '') for node in chain([big, next(selected)], selected)) 
     except StopIteration as e: 
      pass 

for text in get_text(html, 'big', 'a'): 
    print text 
Cuestiones relacionadas