58

私が理解できることから、Pythonの2つの主要なHTML解析ライブラリはlxmlとBeautifulSoupです。私が取り組んでいるプロジェクトにBeautifulSoupを選択しましたが、構文を少し習得して理解しやすくする以外の特別な理由はありません。しかし、多くの人がlxmlを好むようで、lxmlの方が速いと聞いています。

だから私は一方が他方よりも優れているのだろうかと思っていますか?いつlxmlを使用したいのですか?また、BeautifulSoupを使用したほうがよいのはいつですか?検討する価値のある他のライブラリはありますか?

4

7 に答える 7

26

PyqueryPythonへのjQueryセレクターインターフェイスを提供します(内部でlxmlを使用)。

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

それは本当に素晴らしいです、私はもう何も使用しません。

于 2009-12-17T18:48:09.913 に答える
22

まず第一に、BeautifulSoup はもはや積極的にメンテナンスされておらず、著者は lxml などの代替手段を推奨しています。

リンク先のページから引用:

Beautiful Soup のバージョン 3.1.0 は、バージョン 3.0.8 よりも実際の HTML でのパフォーマンスが大幅に低下しています。最も一般的な問題は、タグの不適切な処理、「不正な開始タグ」エラー、および「不適切な終了タグ」エラーです。このページでは、何が起こったのか、どのように問題に対処するのか、そして今できることを説明します。

このページは 2009 年 3 月に作成されました。その後、3.1 シリーズに代わって 3.2 シリーズがリリースされ、4.x シリーズの開発が開始されました。このページは歴史的な目的のために残ります。

tl;dr

代わりに 3.2.0 を使用してください。

于 2009-12-17T14:13:22.907 に答える
17

要約すると、lxml超高速の製品品質の html および xml パーサーとして位置付けられます。ちなみに、soupparserBeautifulSoup の機能にフォールバックするモジュールも含まれています。BeautifulSoupは 1 人で行うプロジェクトであり、時間を節約して、不適切な形式の html または xml からデータをすばやく抽出できるように設計されています。

lxml のドキュメントには、両方のパーサーに長所と短所があると記載されています。このため、前後に切り替えることができるようにlxml用意されています。soupparser引用、

BeautifulSoup は別の解析アプローチを使用します。これは実際の HTML パーサーではありませんが、正規表現を使用してタグ スープを調べます。したがって、より寛容な場合もあれば、あまり良くない場合もあります。lxml/libxml2 が破損した HTML をより適切に解析および修正することは珍しくありませんが、BeautifulSoup はエンコーディング検出の優れたサポートを備えています。どのパーサーがより適切に機能するかは、入力に大きく依存します。

結局のところ、彼らはこう言っています。

このパーサーを使用することの欠点は、lxml の HTML パーサーよりもはるかに遅いことです。したがって、パフォーマンスが重要な場合は、特定のケースのフォールバックとしてのみスープパーサーを使用することを検討してください。

私がそれらを正しく理解していれば、それはスープパーサーがより堅牢であることを意味します---正規表現を使用して不正な形式のタグの「スープ」を処理できます--一方、lxmlより単純で、物事を解析してツリーを構築するだけです期待するでしょう。forBeautifulSoupだけでなく、それ自体にも当てはまると思います。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))

(同じソース: http://lxml.de/elementsoup.html )。

BeautifulSoupの作成者の言葉で、

それでおしまい!楽しむ!みんなの時間を節約するために Beautiful Soup を書きました。慣れれば、デザインの悪い Web サイトからわずか数分でデータを取り出せるようになります。コメントがある場合、問題が発生した場合、または Beautiful Soup を使用するプロジェクトについて知りたい場合は、メールをお送りください。

 --Leonard

Beautiful Soupのドキュメントから引用。

これが明確になったことを願っています。スープは、設計が不十分な Web サイトからデータを抽出する時間を節約できるように設計された、素晴らしい 1 人プロジェクトです。目標は、今すぐ時間を節約して仕事を終わらせることであり、必ずしも長期的に時間を節約することではなく、ソフトウェアのパフォーマンスを最適化することでもありません。

また、lxml の Web サイトから、

lxml は Python Package Index から 200 万回以上ダウンロードされており、Linux や MacOS-X などの多くのパッケージ ディストリビューションで直接利用することもできます。

そして、Why lxml?から。

C ライブラリ libxml2 と libxslt には大きなメリットがあります:... 標準準拠... フル機能... 高速。速い!速い!... lxml は libxml2 と libxslt の新しい Python バインディングです...

于 2013-10-23T18:25:30.217 に答える
11

BeautifulSoup を使用しないでください 。lxml.soupparserを使用すると、lxml のパワーの上に座って、本当に壊れたくだらない HTML を処理する BeautifulSoup の良い部分を使用できます。

于 2009-12-17T14:24:12.630 に答える
5

HTMLの解析にlxmlを使用して大成功を収めました。"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()
于 2009-12-17T14:19:18.697 に答える
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. 
于 2016-03-20T10:03:18.290 に答える
0

やや時代遅れの速度比較がここにあります。速度の違いが劇的に見えるため、明らかに lxml を推奨しています。

于 2012-12-08T13:42:45.317 に答える