Разбор HTML в python - lxml или BeautifulSoup? Какой из них лучше для каких целей? - PullRequest
54 голосов
/ 17 декабря 2009

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

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

Ответы [ 7 ]

26 голосов
/ 17 декабря 2009

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

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

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

22 голосов
/ 17 декабря 2009

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

Цитирование со связанной страницы:

Версия 3.1.0 Beautiful Soup делает значительно хуже в реальном HTML чем версия 3.0.8. Большинство общие проблемы решаются теги неверно, "неправильное начало" тег "ошибки" и "плохой конец тега" ошибки. Эта страница объясняет, что случилось, как проблема будет решена, и что вы можете сделать прямо сейчас.

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

Т.Л., др

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

14 голосов
/ 23 октября 2013

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

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

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

В конце они говорят,

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

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

Они также показывают, как извлечь выгоду из обнаружения кодировки 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.

 --Leonard

Цитируется по документации Beautiful Soup .

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

Также с веб-сайта lxml ,

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

А с Почему lxml? ,

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

11 голосов
/ 17 декабря 2009

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

5 голосов
/ 17 декабря 2009

Я с большим успехом использовал 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()
1 голос
/ 20 марта 2016

Конечно, я бы использовал 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. 
0 голосов
/ 08 декабря 2012

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

...