Usando o módulo Beautiful Soup Python para substituir tags por texto simples
estou usandoSopa Bonita para extrair 'conteúdo' de páginas da web. Eu sei que algumas pessoas perguntaram issoquestão antes e todos eles foram apontados para sopa bonita e é assim que eu comecei com ele.
Consegui obter a maior parte do conteúdo com sucesso, mas estou enfrentando alguns desafios com tags que fazem parte do conteúdo. (Eu estou começando com uma estratégia básica de: se houver mais de x-chars em um nó, então é conteúdo). Vamos pegar o código html abaixo como exemplo:
<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)
Quando eu uso o código acima para chegar ao texto longo, ele quebra (o texto identificado será iniciado a partir de 'e esperemos que ..') nas tags. Então eu tentei substituir a tag com texto simples da seguinte forma:
anchors = soup.findAll('a')
for a in anchors:
a.replaceWith('plain text')
O acima não funciona porque o Beautiful Soup insere a string como um NavigableString e isso causa o mesmo problema quando eu uso findAll com o len (x)> 20. Eu posso usar expressões regulares para analisar o html como texto simples primeiro, limpar tudo as tags indesejadas e, em seguida, chamar Beautiful Soup. Mas eu gostaria de evitar o processamento do mesmo conteúdo duas vezes - estou tentando analisar essas páginas para que eu possa mostrar um trecho de conteúdo para um determinado link (muito parecido com o Facebook Share) - e se tudo for feito com Beautiful Soup, Eu presumo que seja mais rápido.
Então, minha pergunta: existe uma maneira de 'limpar tags' e substituí-las por 'plain text' usando Beautiful Soup. Se não, qual será a melhor maneira de fazer isso?
Obrigado por suas sugestões!
Atualizar: O código de Alex funcionou muito bem para o exemplo. Eu também tentei vários casos de borda e todos eles funcionaram bem (com a modificação abaixo). Então eu dei um tiro em um site da vida real e me deparo com questões que me confundem.
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
Quando executo o código acima, recebo o seguinte erro:
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'
Quando eu olho para o código HTML, 'Mantenha-se atualizado ..' não tem nenhum irmão anterior (eu não fiz como o irmão anterior funcionou até que eu vi o código do Alex e com base no meu teste parece que está procurando por 'texto' Portanto, se não houver um irmão anterior, fico surpreso que ele não esteja passando pela lógica if de a.PreviousSibling é None e a; nextSibling é None.
Você poderia, por favor, me avisar o que estou fazendo errado?
-conhecimento