Синтаксический анализ HTML в python-lxml или BeautifulSoup? Что из этого лучше для каких целей?

из того, что я могу разобрать, две основные библиотеки синтаксического анализа HTML в Python-это lxml и BeautifulSoup. Я выбрал BeautifulSoup для проекта, над которым я работаю, но я выбрал его без особых причин, кроме как найти синтаксис немного легче учиться и понимать. Но я вижу, что многие люди предпочитают lxml, и я слышал, что lxml быстрее.

Итак, мне интересно, каковы преимущества одного над другим? Когда я хочу использовать lxml и когда я буду лучше с помощью BeautifulSoup? Есть ли другие библиотеки, которые стоит рассмотреть?

7 ответов


для начала, BeautifulSoup больше не поддерживается, и автор даже рекомендует альтернатив например, lxml.

цитирую по ссылке:

версия 3.1.0 красивый суп делает значительно хуже на реальном HTML чем версия 3.0.8 делает. Самый общие проблемы теги неправильно, " неправильный старт тег "ошибки и ошибки" bad end tag". На этой странице объясняется, что произошло, как проблема будет решена, и что ты можешь сделать прямо сейчас.

эта статья была первоначально написана в В марте 2009 года. С тех пор, серия 3.2 был выпущен, заменив 3.1 серия, и развитие 4.икс серия уже началась. Эта страница останется до исторического цели.

tl; dr

вместо этого используйте 3.2.0.


Pyquery предоставляет интерфейс селектора jQuery Python (используя lxml под капотом).

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

это действительно потрясающе, я больше ничего не использую.


в целом, lxml позиционируется как молниеносный качественный html и xml парсер, который, кстати, также включает в себя soupparser модуль, чтобы вернуться к функциональности BeautifulSoup. BeautifulSoup это проект для одного человека, призванный сэкономить ваше время, чтобы быстро извлечь данные из плохо сформированного html или xml.

документация lxml говорит, что оба парсера имеют преимущества и недостатки. По этой причине, lxml предоставляет soupparser Так что вы можете переключаться туда-сюда. Цитируя,

BeautifulSoup использует другой подход разбора. Это не настоящий HTML парсер, но использует регулярные выражения для погружения через суп тегов. Это поэтому в одних случаях он более снисходителен, а в других менее добр. Это не редкость, что lxml / libxml2 лучше анализирует и исправляет сломанный HTML, но BeautifulSoup имеет поддержку превосходство для определения кодировки. это очень многое зависит от ввода, который работает парсер лучше.

в конце концов они говорят:

недостатком использования этого анализатора является то, что он гораздо медленнее чем синтаксический анализатор HTML lxml. поэтому, если производительность имеет значение, вы можете захотеть рассматривать использование soupparser только как запасной вариант для определенных случаев.

если я правильно их понимаю, это означает, что суп-парсер более надежный - - - он может иметь дело с" супом " из деформированных теги с помощью регулярных выражений --- а lxml является более простым и просто анализирует вещи и строит дерево, как и следовало ожидать. Я предполагаю, что это также относится к BeautifulSoup само собой, не только soupparser на lxml.

они также показывают, как использовать BeautifulSoup's кодирования обнаружения, в то же время быстро разбора с 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'ы создатель,

вот именно! Получайте удовольствие! Я написал прекрасный суп, чтобы сэкономить время. Как только вы привыкнете к этому, вы сможете извлекать данные из плохо продуманные сайты всего за несколько минут. Отправьте мне письмо, если вы есть какие-либо комментарии, проблемы или хотите, чтобы я знал о вашем проект, который использует красивый суп.

 --Leonard

цитата из красивый суп документация.

я надеюсь, что это теперь четкий. Суп-это блестящий проект для одного человека, призванный сэкономить ваше время на извлечение данных из плохо разработанных веб-сайтов. Цель состоит в том, чтобы сэкономить ваше время прямо сейчас, чтобы выполнить работу, не обязательно экономить ваше время в долгосрочной перспективе и, безусловно, не оптимизировать производительность вашего программного обеспечения.

С веб-сайт lxml,

lxml был загружен из индекса пакета Python более двух миллион раз и также доступный сразу в много пакет дистрибутивы, например, для Linux или MacOS-X.

и почему lxml?,

библиотеки C libxml2 и libxslt имеют огромные преимущества:... Соответствующий стандартам... Полнофункциональный... быстрый. быстро! Быстро! ... библиотека lxml является новой привязкой Python для libxml2 и libxslt...


Не используйте BeautifulSoup, используйте библиотека lxml.суппарсер тогда вы сидите на вершине власти lxml и можете использовать хорошие биты BeautifulSoup, которые должны иметь дело с действительно сломанным и дрянным HTML.


Я с большим успехом использовал 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()

конечно, я бы использовал 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. 

несколько устаревшее сравнение скорости можно найти здесь, что явно рекомендует lxml, поскольку различия в скорости кажутся радикальными.