Pregunta

Estoy tratando de extraer texto de páginas html arbitrarias. Algunas de las páginas (sobre las cuales no tengo control) tienen HTML o scripts mal formados que hacen que esto sea difícil. También estoy en un entorno de alojamiento compartido, por lo que puedo instalar cualquier lib de Python, pero no puedo instalar lo que quiera en el servidor.

pyparsing y html2text.py tampoco parecían funcionar para páginas html mal formadas.

La URL de ejemplo es http://apnews.myway.com/article/20091015/ D9BB7CGG1.html

Mi implementación actual es aproximadamente la siguiente:

# 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 

si beautifulsoup todavía no funciona, entonces recurro a una heurística de mirar el primer carácter, el último carácter (para ver si parece que es una línea de código # <; y tomar una muestra de línea y luego verifique si las fichas son palabras en inglés o números. Si algunas de las fichas son palabras o números, entonces supongo que la línea es código.

Podría usar el aprendizaje automático para inspeccionar cada línea, pero eso parece un poco costoso y probablemente tendría que entrenarlo (ya que no sé mucho sobre máquinas de aprendizaje no supervisadas) y, por supuesto, escribirlo también.

Cualquier consejo, herramientas, estrategias serían bienvenidas. También me doy cuenta de que la última parte de eso es bastante desordenada ya que si obtengo una línea que se determina que contiene código, actualmente descarto toda la línea, incluso si hay una pequeña cantidad de texto en inglés real en la línea.

¿Fue útil?

Solución

Intenta no reír, pero:

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 tengas lince!

Otros consejos

Bueno, depende de cuán buena sea la solución. Tuve un problema similar al importar cientos de páginas html antiguas a un nuevo sitio web. Básicamente lo hice

# 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 )

y funcionó, pero por supuesto los documentos podrían ser tan malos que incluso BS no puede salvar mucho.

BeautifulSoup hará mal con HTML mal formado. ¿Qué pasa con algunos 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.'

Luego puede armar una lista de etiquetas válidas de las que desea extraer información.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top