用python-lxml或BeautifulSoup解析HTML?哪一个更好用于什么目的?

用python-lxml或BeautifulSoup解析HTML?哪一个更好用于什么目的?,python,beautifulsoup,html-parsing,lxml,Python,Beautifulsoup,Html Parsing,Lxml,据我所知,Python中的两个主要HTML解析库是lxml和BeautifulSoup。我选择BeautifulSoup作为我正在进行的一个项目,但我选择它并不是为了别的原因,只是因为我觉得语法更容易学习和理解。但我看到很多人似乎都喜欢lxml,我听说lxml速度更快 所以我想知道一个比另一个有什么优势?我什么时候想使用lxml,什么时候使用BeautifulSoup会更好?还有其他库值得考虑吗?首先,BeautifulSoup不再积极维护,例如lxml 从链接页面引用: Beautiful S

据我所知,Python中的两个主要HTML解析库是lxml和BeautifulSoup。我选择BeautifulSoup作为我正在进行的一个项目,但我选择它并不是为了别的原因,只是因为我觉得语法更容易学习和理解。但我看到很多人似乎都喜欢lxml,我听说lxml速度更快

所以我想知道一个比另一个有什么优势?我什么时候想使用lxml,什么时候使用BeautifulSoup会更好?还有其他库值得考虑吗?

首先,BeautifulSoup不再积极维护,例如lxml

从链接页面引用:

Beautiful Soup的3.1.0版 在现实世界的HTML上,情况要糟糕得多 比版本3.0.8做的更多。最 常见的问题是如何处理 标签不正确,“启动格式不正确” 标记“错误”和“坏端标记”错误。 这一页解释了发生了什么,如何发生的 这个问题将得到解决,并且 你现在能做什么

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

tl;dr

改用3.2.0


我已经使用lxml成功地解析了HTML。它似乎在处理“soupy”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()
导入单元测试
从StringIO导入StringIO
从lxml导入etree
类TestLxmlStuff(unittest.TestCase):
坏的_html=“”
测试!
这是标题
这里有一些文字
还有一些文字
大胆的
一行
测试1
测试2
跨越两个
"""
def测试(自我):
“”“测试lxml对非常糟糕的HTML的解析”“”
parser=etree.HTMLParser()
tree=etree.parse(StringIO(self.bad_html),解析器)
self.assertEqual(len(tree.xpath('//tr')),3)
self.assertEqual(len(tree.xpath('//td')),3)
self.assertEqual(len(tree.xpath('//i')),0)
#打印(etree.tostring(tree.getroot(),pretty\u print=False,method=“html”))
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
unittest.main()

不要使用BeautifulSoup,使用
然后,您就掌握了lxml的强大功能,可以使用BeautifulSoup的优秀功能来处理真正破碎和糟糕的HTML

Pyquery
为Python提供jQuery选择器接口(在后台使用lxml)


这真是太棒了,我不再使用其他任何东西了。

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

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

表示这两种解析器都有优点和缺点。因此,
lxml
提供了一个
soupparser
,因此您可以来回切换。引用

BeautifulSoup使用不同的解析方法。它不是一个真正的HTML 语法分析器,但使用正则表达式来浏览标记汤。它是 因此,在某些情况下,宽容更多,而在另一些情况下,宽容更少。它是 lxml/libxml2能够更好地解析和修复损坏的HTML,这并不少见, 但是BeautifulSoup在编码检测方面有更高的支持它 这在很大程度上取决于输入哪个解析器工作得更好。

最后他们说,

使用此解析器的缺点是,它比 lxml的HTML解析器因此,如果性能很重要,您可能需要 考虑仅使用SoupPARSER作为某些情况下的回退。<强> < /P> 如果我理解正确,这意味着soup解析器更健壮——它可以通过使用正则表达式来处理格式错误的标记的“soup”——而
lxml
更简单,只需像您所期望的那样解析内容并构建树。我假设它也适用于
BeautifulSoup
本身,而不仅仅适用于
lxml的
soupparser

它们还展示了如何从
BeautifulSoup
的编码检测中获益,同时仍然可以使用
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))
(同一来源:)

BeautifulSoup
的创建者的话来说

就这样!玩得高兴我写了漂亮的汤来节省大家的时间。 一旦你习惯了它,你应该能够把数据从数据中分离出来 设计糟糕的网站只需几分钟。如果需要,请给我发电子邮件 有任何意见,遇到问题,或想让我知道你的 使用漂亮汤的项目

 --Leonard
引自

我希望这一点现在已经清楚了。“汤”是一个出色的单人项目,旨在节省您从设计拙劣的网站中提取数据的时间。我们的目标是现在就为您节省时间,完成工作,而不是从长远来看为您节省时间,当然也不是优化软件的性能

而且从

lxml已经从Python包索引下载了两次以上 百万次,也可直接在多个软件包中提供 发行版,例如Linux或MacOS-X

而且,从

C库libxml2和libxslt有巨大的好处:。。。 符合标准。。。
<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.