Próbuję zeskrobać mowę z witryny za pomocą pięknejSoup. Jednak spotykam się z problemami, ponieważ przemówienie jest podzielone na wiele różnych akapitów. Jestem niezwykle nowy w programowaniu i masz problemy z zastanawieniem, jak sobie z tym poradzić. HTML strony wygląda tak:

<span class="displaytext">Thank you very much. Mr. Speaker, Vice President Cheney, 
Members of Congress, distinguished guests, fellow citizens: As we gather tonight, our Nation is    
at war; our economy is in recession; and the civilized world faces unprecedented dangers. 
Yet, the state of our Union has never been stronger.
<p>We last met in an hour of shock and suffering. In 4 short months, our Nation has comforted the victims, 
begun to rebuild New York and the Pentagon, rallied a great coalition, captured, arrested, and  
rid the world of thousands of terrorists, destroyed Afghanistan's terrorist training camps, 
saved a people from starvation, and freed a country from brutal oppression. 
<p>The American flag flies again over our Embassy in Kabul. Terrorists who once occupied 
Afghanistan now occupy cells at Guantanamo Bay. And terrorist leaders who urged followers to 
sacrifice their lives are running for their own.

Kontynuuje tak, że przez chwilę, z wieloma tagami akapitów. Próbuję wyodrębnić cały tekst w rozpiętości.

Próbowałem kilku różnych sposobów na zdobycie tekstu, ale oba nie otrzymali tego tekstu.

Pierwszy wypróbowany jest:

import urllib2,sys
from BeautifulSoup import BeautifulSoup, NavigableString

address = 'http://www.presidency.ucsb.edu/ws/index.php?pid=29644&st=&st1=#axzz1fD98kGZW'
html = urllib2.urlopen(address).read()

soup = BeautifulSoup(html)
thespan = soup.find('span', attrs={'class': 'displaytext'})
print thespan.string

Co daje mi:

Pan Speaker, wiceprezes Cheney, członkowie kongresu, wybitni goście, koledzy obywatele: jak się zebramy dziś wieczorem, nasz naród jest w stanie wojny; Nasza gospodarka jest w recesji; a cywilizowany świat stoi przed bezprecedensowym niebezpieczeństwami. Jednak stan naszego związku nigdy nie był silniejszy.

To jest część tekstu do pierwszego tagu akapitu. Potem próbowałem:

import urllib2,sys
from BeautifulSoup import BeautifulSoup, NavigableString

address = 'http://www.presidency.ucsb.edu/ws/index.php?pid=29644&st=&st1=#axzz1fD98kGZW'
html = urllib2.urlopen(address).read()

soup = BeautifulSoup(html)
thespan = soup.find('span', attrs={'class': 'displaytext'})
for section in thespan:
     paragraph = section.findNext('p')
     if paragraph and paragraph.string:
         print '>', paragraph.string
     else:
         print '>', section.parent.next.next.strip()

Dało mi to tekst między tagiem akapitu pierwszego a tagiem akapitu drugiego. Szukam sposobu, aby uzyskać cały tekst, zamiast tylko sekcji.

10
user1074057 30 listopad 2011, 23:16

3 odpowiedzi

Najlepsza odpowiedź
import urllib2,sys
from BeautifulSoup import BeautifulSoup

address = 'http://www.presidency.ucsb.edu/ws/index.php?pid=29644&st=&st1=#axzz1fD98kGZW'
soup = BeautifulSoup(urllib2.urlopen(address).read())

span = soup.find("span", {"class":"displaytext"})  # span.string gives you the first bit
paras = [x.contents[0] for x in span.findAllNext("p")]  # this gives you the rest
# use .contents[0] instead of .string to deal with last para that's not well formed

print "%s\n\n%s" % (span.string, "\n\n".join(paras))

Jak wskazano w komentarzach, powyżej nie działa tak dobrze, jeśli znaczniki <p> zawierają bardziej zagnieżdżone znaczniki. Można go rozwiązać przy użyciu:

paras = ["".join(x.findAll(text=True)) for x in span.findAllNext("p")]

Jednak to nie działa zbyt dobrze z ostatnim <p>, który nie ma tagu zamykającego. Obejście Hacky byłoby traktowanie tego inaczej. Na przykład:

import urllib2,sys
from BeautifulSoup import BeautifulSoup

address = 'http://www.presidency.ucsb.edu/ws/index.php?pid=29644&st=&st1=#axzz1fD98kGZW'
soup = BeautifulSoup(urllib2.urlopen(address).read())
span = soup.find("span", {"class":"displaytext"})  
paras = [x for x in span.findAllNext("p")]

start = span.string
middle = "\n\n".join(["".join(x.findAll(text=True)) for x in paras[:-1]])
last = paras[-1].contents[0]
print "%s\n\n%s\n\n%s" % (start, middle, last)
8
Shawn Chin 30 listopad 2011, 21:28

Oto jak będzie to zrobione za pomocą {X0}}:

import lxml.html as lh

tree = lh.parse('http://www.presidency.ucsb.edu/ws/index.php?pid=29644&st=&st1=#axzz1fD98kGZW')

text = tree.xpath("//span[@class='displaytext']")[0].text_content()

Alternatywnie, odpowiedzi na to pytanie obejmuje, jak osiągnąć to samo za pomocą pięknejSoup: BeautifulSoup - łatwy sposób, aby uzyskać zawartość wolna od HTML .

Funkcja pomocnika z zaakceptowanej odpowiedzi:

def textOf(soup):
    return u''.join(soup.findAll(text=True))
2
Community 23 maj 2017, 12:17

Powinieneś spróbować:

soup.span.renderContents()
0
Ofir Farchy 2 listopad 2012, 12:20