Análisis de HTML en python – lxml o BeautifulSoup? ¿Cuál de estos es mejor para qué tipo de propósitos?

Por lo que puedo ver, las dos bibliotecas de análisis HTML principales en Python son lxml y BeautifulSoup. He elegido BeautifulSoup para un proyecto en el que estoy trabajando, pero lo elegí por una razón en particular, además de encontrar la syntax un poco más fácil de aprender y entender. Pero veo que muchas personas parecen estar a favor de lxml y he escuchado que lxml es más rápido.

Así que me pregunto cuáles son las ventajas de uno sobre el otro. ¿Cuándo querría usar lxml y cuándo sería mejor usar BeautifulSoup? ¿Hay otras bibliotecas que valga la pena considerar?

Para empezar, BeautifulSoup ya no se mantiene activamente, y el autor incluso recomienda alternativas como lxml.

Citando desde la página enlazada:

La versión 3.1.0 de Beautiful Soup hace mucho peor en HTML del mundo real que la versión 3.0.8. Los problemas más comunes son el manejo incorrecto de tags, errores de “etiqueta de inicio con formato incorrecto” y errores de “etiqueta de final incorrecta”. Esta página explica qué sucedió, cómo se abordará el problema y qué puede hacer ahora.

Esta página se escribió originalmente en marzo de 2009. Desde entonces, la serie 3.2 se ha lanzado, reemplazando a la serie 3.1, y el desarrollo de la serie 4.x ha comenzado. Esta página se mantendrá para propósitos históricos.

tl; dr

Utilice 3.2.0 en su lugar.

Pyquery proporciona la interfaz de jQuery selector a Python (usando lxml debajo del capó).

http://pypi.python.org/pypi/pyquery

Es realmente increíble, ya no uso nada más.

En resumen, lxml se posiciona como un analizador html y xml de calidad de producción lxml rápido que, por cierto, también incluye un módulo soupparser para recurrir a la funcionalidad de BeautifulSoup. BeautifulSoup es un proyecto de una sola persona, diseñado para ahorrarle tiempo para extraer rápidamente datos de html o xml mal formados.

La documentación de lxml dice que ambos analizadores tienen ventajas y desventajas. Por esta razón, lxml proporciona un soupparser para que pueda alternar. Citando,

BeautifulSoup utiliza un enfoque de análisis diferente. No es un analizador HTML real, pero utiliza expresiones regulares para sumergirse en la sopa de tags. Por lo tanto, es más indulgente en algunos casos y menos bueno en otros. No es raro que lxml / libxml2 analice y corrija mejor el HTML dañado, pero BeautifulSoup tiene un excelente soporte para la detección de la encoding. Depende mucho de la entrada en la que el analizador funcione mejor.

Al final están diciendo,

La desventaja de usar este analizador es que es mucho más lento que el analizador HTML de lxml. Entonces, si el rendimiento es importante, es posible que desee considerar el uso de soupparser solo como una alternativa para ciertos casos.

Si los comprendo correctamente, significa que el analizador de sopas es más robusto, puede manejar una “sopa” de tags mal formadas mediante el uso de expresiones regulares, mientras que lxml es más sencillo y simplemente analiza las cosas y construye un árbol como usted esperaría Supongo que también se aplica a BeautifulSoup , no solo al soupparser para lxml .

También muestran cómo beneficiarse de la detección de encoding de BeautifulSoup , mientras analizan rápidamente con lxml :

 >>> from BeautifulSoup import UnicodeDammit >>> def decode_html(html_string): ... converted = UnicodeDammit(html_string, isHTML=True) ... if not converted.unicode: ... raise UnicodeDecodeError( ... "Failed to detect encoding, tried [%s]", ... ', '.join(converted.triedEncodings)) ... # print converted.originalEncoding ... return converted.unicode >>> root = lxml.html.fromstring(decode_html(tag_soup)) 

(La misma fuente: http://lxml.de/elementsoup.html ).

En palabras del creador de BeautifulSoup ,

¡Eso es! ¡Que te diviertas! Escribí Beautiful Soup para ahorrarle tiempo a todos. Una vez que se haya acostumbrado a eso, debería poder separar los datos de sitios web mal diseñados en tan solo unos minutos. Envíeme un correo electrónico si tiene algún comentario, tiene problemas o quiere que sepa sobre su proyecto que utiliza Beautiful Soup.

  --Leonard 

Citado de la documentación de Beautiful Soup .

Espero que esto esté ahora claro. La sopa es un shiny proyecto de una sola persona diseñado para ahorrarle tiempo para extraer datos de sitios web mal diseñados. El objective es ahorrarle tiempo ahora, hacer el trabajo, no necesariamente ahorrarle tiempo a largo plazo y, definitivamente, no optimizar el rendimiento de su software.

Además, desde el sitio web de lxml ,

lxml se ha descargado del Índice de Paquetes de Python más de dos millones de veces y también está disponible directamente en muchas distribuciones de paquetes, por ejemplo, para Linux o MacOS-X.

Y, desde ¿Por qué lxml? ,

Las bibliotecas C, libxml2 y libxslt tienen enormes beneficios: … Cumplen con los estándares … Con todas las funciones … rápido. ¡rápido! ¡RÁPIDO! … lxml es un nuevo enlace de Python para libxml2 y libxslt …

No uses BeautifulSoup, usa lxml.soupparser, entonces estás sentado sobre el poder de lxml y puedes usar los buenos bits de BeautifulSoup, que es para lidiar con HTML realmente defectuoso y horrible.

He usado lxml con gran éxito para analizar HTML. Parece que también hace un buen trabajo en el manejo de HTML “soposo”. Lo recomiendo altamente

Aquí hay una prueba rápida que tuve para intentar manejar un poco de HTML feo:

 import unittest from StringIO import StringIO from lxml import etree class TestLxmlStuff(unittest.TestCase): bad_html = """  Test!  

Here's a heading

Here's some text

And some more text Bold!

row
test1 test2
spanning two

""" def test_soup(self): """Test lxml's parsing of really bad HTML""" parser = etree.HTMLParser() tree = etree.parse(StringIO(self.bad_html), parser) self.assertEqual(len(tree.xpath('//tr')), 3) self.assertEqual(len(tree.xpath('//td')), 3) self.assertEqual(len(tree.xpath('//i')), 0) #print(etree.tostring(tree.getroot(), pretty_print=False, method="html")) if __name__ == '__main__': unittest.main()

Seguro que usaría EHP. Es más rápido que lxml, mucho más elegante y más fácil de usar.

Revisa. https://github.com/iogf/ehp

  foo  from ehp import * data = '''   Hello world.   ''' html = Html() dom = html.feed(data) for ind in dom.find('em'): print ind.text() 

Salida:

 Hello world. 

Aquí se puede encontrar una comparación de velocidad algo desactualizada, que claramente recomienda lxml, ya que las diferencias de velocidad parecen drásticas.