2012-08-04 15 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> 
... 
""" 

Chcę, aby cały tekst między początkowym tagiem big upto przed pierwszym wystąpieniem tagu a. Oznacza to, że jeśli weźmiemy ten przykład, muszę uzyskać ciąg znaków w postaci (iterable).Jak uzyskać dostęp do całego tekstu między dwoma określonymi znacznikami za pomocą BeautifulSoup?

Odpowiedz

3

chciałbym uniknąć nextSibling, począwszy od pytania, chcesz to wszystko aż do następny <a>, niezależnie od tego, czy jest to element rodzeństwa, elementu nadrzędnego czy podrzędnego.

Dlatego uważam, że najlepszym sposobem jest znalezienie węzła, który jest następnym elementem <a> i rekurencyjnie do tego czasu, dodając każdy napotkany łańcuch jako napotkany. Może być konieczne wyczyszczenie poniższego kodu, jeśli HTML znacznie różni się od próbki, ale coś takiego powinno zadziałać:

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

tak, dokładnie tak, chcę dołączaj wszystko do następnego tagu "a" i może istnieć dowolna liczba tagów, tekstów pomiędzy pierwszym znacznikiem "dużym" a pierwszym znacznikiem "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' nie może być stosowany jako Chcę to każdy tekst zapisu do pierwszego wystąpienia tagu„a” –

1

można zrobić tak:

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 

Szczegółowe sprawdzić DOM Ruch ze BeautifulSoup z here

+0

ta zwraca„iterable”zamiast„(iterable)” – anotherdave

5

Podejście iteracyjne.

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 
Powiązane problemy