Pergunta

Estou tentando extrair texto de páginas HTML arbitrárias. Algumas das páginas (sobre as quais não tenho controle) têm HTML ou scripts malformados que dificultam isso. Também estou em um ambiente de hospedagem compartilhado, para que eu possa instalar qualquer Python Lib, mas não posso simplesmente instalar o que quiser no servidor.

Pyparsing e html2text.py também não pareciam funcionar para páginas HTML malformadas.

Exemplo de URL é http://apnews.myway.com/article/20091015/d9bb7cgg1.html

Minha implementação atual é aproximadamente o seguinte:

# Try using BeautifulSoup 3.0.7a
soup = BeautifulSoup.BeautifulSoup(s) 
comments = soup.findAll(text=lambda text:isinstance(text,Comment))
[comment.extract() for comment in comments]
c=soup.findAll('script')
for i in c:
    i.extract()    
body = bsoup.body(text=True)
text = ''.join(body) 
# if BeautifulSoup  can't handle it, 
# alter html by trying to find 1st instance of  "<body" and replace everything prior to that, with "<html><head></head>"
# try beautifulsoup again with new html 

Se o BeautifulSoup ainda não funcionar, então eu recorrei a usar uma heurística de olhar para o 1º char, último char (para ver se eles parecem ser uma linha de código # <; e pegar uma amostra da linha e depois verifique se os tokens são palavras em inglês ou números. Se alguns dos tokens forem palavras ou números, acho que a linha é o código.

Eu poderia usar o aprendizado de máquina para inspecionar cada linha, mas isso parece um pouco caro e provavelmente teria que treiná -la (já que não sei muito sobre máquinas de aprendizado sem supervisão) e, é claro, escrevê -lo também.

Qualquer conselho, ferramentas e estratégias seriam bem -vindos. Também percebo que a última parte disso é bastante confusa, pois, se eu tiver uma linha que determine o código, atualmente joguei fora a linha inteira, mesmo que haja uma pequena quantidade de texto em inglês real na linha.

Foi útil?

Solução

Tente não rir, mas:

class TextFormatter:
    def __init__(self,lynx='/usr/bin/lynx'):
        self.lynx = lynx

    def html2text(self, unicode_html_source):
        "Expects unicode; returns unicode"
        return Popen([self.lynx, 
                      '-assume-charset=UTF-8', 
                      '-display-charset=UTF-8', 
                      '-dump', 
                      '-stdin'], 
                      stdin=PIPE, 
                      stdout=PIPE).communicate(input=unicode_html_source.encode('utf-8'))[0].decode('utf-8')

Espero que você tenha Lynx!

Outras dicas

Bem, depende de quão boa a solução deve ser. Eu tive um problema semelhante, importando centenas de páginas HTML antigas em um novo site. Eu basicamente fiz

# remove all that crap around the body and let BS fix the tags
newhtml = "<html><body>%s</body></html>" % (
    u''.join( unicode( tag ) for tag in BeautifulSoup( oldhtml ).body.contents ))
# use html2text to turn it into text
text = html2text( newhtml )

E funcionou, mas é claro que os documentos podem ser tão ruins que mesmo o BS não consegue salvar muito.

O BeautifulSoup fará mal com o HTML malformado. Que tal algum regex-fu?

>>> import re
>>> 
>>> html = """<p>This is paragraph with a bunch of lines
... from a news story.</p>"""
>>> 
>>> pattern = re.compile('(?<=p>).+(?=</p)', re.DOTALL)
>>> pattern.search(html).group()
'This is paragraph with a bunch of lines\nfrom a news story.'

Você pode montar uma lista de tags válidas das quais deseja extrair informações.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top