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

Mon*_*lik 55 python lxml beautifulsoup html-parsing

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

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

mik*_*eal 26

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

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

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


Ale*_*vik 22

对于初学者来说,不再积极维护BeautifulSoup,作者甚至建议使用 lxml等替代品.

从链接页面引用:

版本3.1.0的Beautiful Soup在真实HTML上的表现比3.0.8版本差得多.最常见的问题是错误处理标记,"格式错误的开始标记"错误和"错误结束标记"错误.这个页面解释了发生了什么,如何解决问题,以及你现在可以做些什么.

这个页面最初是在2009年3月写的.从那时起,3.2系列已经发布,取代了3.1系列,并且4.x系列的开发已经开始.此页面将保留用于历史目的.

TL;博士

请改用3.2.0.

  • 恕我直言,这是误导 - 仔细阅读该页面显示`lxml`只是问题版本3.1.0的替代品,其中的问题已在3.2.0中修复,现在甚至版本4在发布的路上只有2几个月前 - 因此该模块几乎"不再积极维护".*请修改答案* (19认同)
  • +1我不知道BeautifulSoup的腐烂,我依赖和崇拜. (9认同)
  • 很高兴看到BeautifulSoup再次得到维护.3.2.0于2010年11月发布---这个答案差不多一年了.. :) (3认同)
  • 当我读到这篇文章时,我认为bs4已经死了.放心地找到"使用3.2.0而不是". (3认同)
  • 我怀疑这是否应该是今天公认的答案。这里的一切都是几乎无用的信息(除了怀旧/历史目的)。 (2认同)

osa*_*osa 15

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

lxml文档说两个解析器都有优点和缺点.因此,lxml提供一个soupparser可以来回切换的设备.引用,

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

最后他们说,

使用此解析器的缺点是它比lxml的HTML解析器得多.因此,如果性能很重要,您可能需要考虑将soupparser仅用作某些情况的后备.

如果我理解正确,这意味着汤解析器更强大 - 它可以通过使用正则表达式来处理格式错误标签的"汤" - 而lxml更直接,只需解析事物并构建一棵树期待.我认为它也适用于BeautifulSoup自己,而不仅仅适用soupparserlxml.

他们还展示了如何从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))
Run Code Online (Sandbox Code Playgroud)

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

BeautifulSoup创作者的话来说,

而已!玩得开心!我写了美丽的汤来节省每个人的时间.一旦你习惯了它,你应该能够在几分钟内从设计不佳的网站中搜集数据.如果您有任何意见,遇到问题或希望我了解您使用Beautiful Soup的项目,请给我发电子邮件.

 --Leonard
Run Code Online (Sandbox Code Playgroud)

引自Beautiful Soup文档.

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

另外,从lxml网站,

lxml已经从Python Package Index下载了200多万次,也可以在许多软件包发行版中直接使用,例如Linux或MacOS-X.

而且,从为什么lxml?,

C库libxml2和libxslt具有巨大的优势:......符合标准......功能齐全......快速.快速!快速!... lxml是libxml2和libxslt的新Python绑定...


Pet*_*son 11

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


ove*_*ink 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()
Run Code Online (Sandbox Code Playgroud)