Użycie modułu Beautiful Soup Python do zastąpienia tagów zwykłym tekstem
ja używamPiękna Zupa wyodrębnić „treść” ze stron internetowych. Wiem, że niektórzy ludzie o to pytalipytanie wcześniej i wszyscy wskazywali na piękną zupę i tak zacząłem z tym.
Udało mi się uzyskać większość treści, ale napotykam na pewne wyzwania z tagami, które są częścią treści. (Zaczynam od podstawowej strategii: jeśli w węźle jest więcej niż x znaków, to jest to treść). Weźmy poniższy kod HTML jako przykład:
<div id="abc">
some long text goes <a href="/"> here </a> and hopefully it
will get picked up by the parser as content
</div>
results = soup.findAll(text=lambda(x): len(x) > 20)
Kiedy używam powyższego kodu, aby uzyskać długi tekst, pęka (zidentyfikowany tekst zacznie się od „i miejmy nadzieję ...”) w tagach. Próbowałem więc zastąpić tag zwykłym tekstem w następujący sposób:
anchors = soup.findAll('a')
for a in anchors:
a.replaceWith('plain text')
Powyższe nie działa, ponieważ Beautiful Soup wstawia ciąg znaków jako ciąg nawigacyjny, co powoduje ten sam problem, gdy używam findAll z len (x)> 20. Mogę użyć wyrażeń regularnych, aby najpierw przeanalizować HTML jako zwykły tekst, usunąć wszystkie niechciane znaczniki, a następnie zadzwoń do Pięknej Zupy. Ale chciałbym uniknąć dwukrotnego przetwarzania tej samej treści - próbuję przeanalizować te strony, aby móc wyświetlić fragment treści dla danego linku (bardzo podobny do Facebook Share) - i jeśli wszystko jest zrobione z Beautiful Soup, Przypuszczam, że będzie szybciej.
Więc moje pytanie: czy istnieje sposób na „wyczyszczenie tagów” i zastąpienie ich „zwykłym tekstem” za pomocą Pięknej Zupy. Jeśli nie, jaki będzie najlepszy sposób, aby to zrobić?
Dziękujemy za sugestie!
Aktualizacja: Kod Alexa działał bardzo dobrze dla przykładowego przykładu. Próbowałem także różnych przypadków krawędzi i wszystkie działały dobrze (z modyfikacją poniżej). Więc dałem mu szansę na prawdziwą stronę internetową i wpadłem na problemy, które mnie łamały.
import urllib
from BeautifulSoup import BeautifulSoup
page = urllib.urlopen('http://www.engadget.com/2010/01/12/kingston-ssdnow-v-dips-to-30gb-size-lower-price/')
anchors = soup.findAll('a')
i = 0
for a in anchors:
print str(i) + ":" + str(a)
for a in anchors:
if (a.string is None): a.string = ''
if (a.previousSibling is None and a.nextSibling is None):
a.previousSibling = a.string
elif (a.previousSibling is None and a.nextSibling is not None):
a.nextSibling.replaceWith(a.string + a.nextSibling)
elif (a.previousSibling is not None and a.nextSibling is None):
a.previousSibling.replaceWith(a.previousSibling + a.string)
else:
a.previousSibling.replaceWith(a.previousSibling + a.string + a.nextSibling)
a.nextSibling.extract()
i = i+1
Po uruchomieniu powyższego kodu pojawia się następujący błąd:
0:<a href="http://www.switched.com/category/ces-2010">Stay up to date with
Switched's CES 2010 coverage</a>
Traceback (most recent call last):
File "parselink.py", line 44, in <module>
a.previousSibling.replaceWith(a.previousSibling + a.string + a.nextSibling)
TypeError: unsupported operand type(s) for +: 'Tag' and 'NavigableString'
Kiedy patrzę na kod HTML, „Bądź na bieżąco ...” nie ma żadnego poprzedniego rodzeństwa (nie wiedziałem, jak poprzedni brat działał, dopóki nie zobaczyłem kodu Alexa i na podstawie moich testów wygląda na to, że szuka „tekstu” przed tagiem). Tak więc, jeśli nie ma poprzedniego rodzeństwa, jestem zaskoczony, że nie przechodzi on przez logikę if.previousSibling jest None i a; nextSibling jest None.
Czy mógłbyś mi powiedzieć, co robię źle?
-ekognium