在python中解析HTML - lxml还是BeautifulSoup?哪种更好用于何种目的?

时间:2009-12-17 14:08:59

标签: python beautifulsoup html-parsing lxml

据我所知,Python中的两个主要HTML解析库是lxml和BeautifulSoup。我选择了BeautifulSoup作为我正在研究的项目,但除了找到更容易学习和理解的语法之外,我选择了它。但是我看到很多人似乎都喜欢lxml,我听说lxml更快。

所以我想知道一个优于另一个的优点是什么?我什么时候想使用lxml?什么时候最好使用BeautifulSoup?还有其他值得考虑的图书馆吗?

7 个答案:

答案 0 :(得分:26)

Pyquery为Python提供了jQuery选择器接口(在引擎盖下使用lxml)。

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

真的很棒,我不再使用其他任何东西了。

答案 1 :(得分:22)

首先,不再积极维护BeautifulSoup,并且the author even recommends alternatives例如lxml。

从链接页面引用:

  

美丽的汤3.1.0版本   在真实世界的HTML上显着恶化   比版本3.0.8。最多   常见的问题是处理   标签错误,“格式错误的开始   标记“错误”和“错误结束标记”错误。   这个页面解释了发生了什么,如何   问题将得到解决,并且   你现在能做什么。

     

此页面最初是用   2009年3月。从那时起,3.2系列   已经发布,取代3.1   系列,以及4.x的开发   系列已经开始。这一页   将保持历史   目的。

     

<强> TL;博士

     

改用3.2.0。

答案 2 :(得分:14)

总之,lxml被定位为闪电般快速的生产质量html和xml解析器,顺便说一下,它还包含一个soupparser模块,可以依赖于BeautifulSoup的功能。 BeautifulSoup是一个单人项目,旨在为您节省时间,以便从格式不正确的html或xml中快速提取数据。

lxml documentation说两种解析器都有优点和缺点。因此,lxml提供了soupparser,因此您可以来回切换。报价,

  

BeautifulSoup使用不同的解析方法。它不是真正的HTML   解析器,但使用正则表达式来跳过标签汤。它是   因此在某些情况下更宽容,在其他情况下则不那么好。它是   并不罕见lxml / libxml2更好地解析和修复损坏的HTML,   但BeautifulSoup对编码检测有很好的支持。的它   很大程度上取决于解析器更好地工作的输入。

最后他们说,

  

使用此解析器的缺点是慢得多   lxml的HTML解析器。 因此,如果性能很重要,您可能会想要   考虑将soupparser仅用作某些案例的后备。

如果我理解正确,这意味着汤解析器更强大 - 它可以通过使用正则表达式来处理格式错误标签的“汤” - 而lxml更直接而且恰到好处解析事物并按照您的预期构建树。我认为它也适用于BeautifulSoup本身,而不仅仅适用于soupparser的{​​{1}}。

他们还展示了如何从lxml的编码检测中受益,同时仍然使用BeautifulSoup快速解析:

lxml

(相同来源:http://lxml.de/elementsoup.html)。

>>> 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)) 的创作者的话来说,

  

就是这样!玩得开心!我写了美丽的汤来节省每个人的时间。   一旦你习惯了它,你应该能够解决数据问题   在短短几分钟内设计糟糕的网站。如果你给我发电子邮件   有任何意见,遇到问题,或希望我了解你的   使用Beautiful Soup的项目。

BeautifulSoup

引自Beautiful Soup documentation

我希望现在已经清楚了。汤是一个精彩的单人项目,旨在为您节省时间从设计不佳的网站中提取数据。目标是为您节省时间,完成工作,不一定能节省您的长期时间,绝对不是为了优化软件的性能。

此外,来自lxml website

  

已经从Python Package Index下载了两个以上的lxml   百万次,也可直接在许多包装中使用   分发,例如对于Linux或MacOS-X。

而且,来自Why lxml?

  

C库libxml2和libxslt有很多好处:...   符合标准......功能齐全......快速。快速!快速! ... lxml   是libxml2和libxslt ...

的新Python绑定

答案 3 :(得分:11)

不要使用BeautifulSoup,请使用 lxml.soupparser然后你就是坐在lxml的强大功能之上,并且可以使用BeautifulSoup的优点来处理真正破碎和糟糕的HTML。

答案 4 :(得分:5)

我使用lxml非常成功地解析HTML。它似乎也很好地处理“汤”HTML。我强烈推荐它。

这是一个快速测试,我试图处理一些丑陋的HTML:

import unittest
from StringIO import StringIO
from lxml import etree

class TestLxmlStuff(unittest.TestCase):
    bad_html = """
        <html>
            <head><title>Test!</title></head>
            <body>
                <h1>Here's a heading
                <p>Here's some text
                <p>And some more text
                <b>Bold!</b></i>
                <table>
                   <tr>row
                   <tr><td>test1
                   <td>test2
                   </tr>
                   <tr>
                   <td colspan=2>spanning two
                </table>
            </body>
        </html>"""

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

答案 5 :(得分:1)

我肯定会使用EHP。它比lxml更快,更优雅,更简单易用。

退房。 https://github.com/iogf/ehp

<body ><em > foo  <font color="red" ></font></em></body>


from ehp import *

data = '''<html> <body> <em> Hello world. </em> </body> </html>'''

html = Html()
dom = html.feed(data)

for ind in dom.find('em'):
    print ind.text()    

输出:

Hello world. 

答案 6 :(得分:0)

可以找到一个有点过时的速度比较here,它明确推荐lxml,因为速度差异似乎很大。