programing

파이썬에서 HTML 구문 분석-lxml 또는 BeautifulSoup?

randomtip 2021. 1. 15. 08:07
반응형

파이썬에서 HTML 구문 분석-lxml 또는 BeautifulSoup? 어떤 목적에 더 좋은 것은 무엇입니까?


내가 알 수 있듯이 Python의 두 가지 주요 HTML 구문 분석 라이브러리는 lxml과 BeautifulSoup입니다. 작업중인 프로젝트에 대해 BeautifulSoup을 선택했지만 구문을 배우고 이해하기 더 쉬운 것을 찾는 것 외에 특별한 이유없이 선택했습니다. 하지만 많은 사람들이 lxml을 선호하는 것 같고 lxml이 더 빠르다고 들었습니다.

그래서 나는 다른 것보다 하나의 장점이 무엇인지 궁금합니다. lxml을 언제 사용하고 싶고 언제 BeautifulSoup을 사용하는 것이 더 나을까요? 고려할만한 다른 라이브러리가 있습니까?


우선 BeautifulSoup은 더 이상 적극적으로 유지 관리되지 않으며 저자 는 lxml과 같은 대안을 권장 합니다.

링크 된 페이지에서 인용 :

Beautiful Soup 3.1.0 버전은 실제 HTML에서 3.0.8 버전보다 훨씬 더 나쁩니다. 가장 일반적인 문제는 잘못된 태그 처리, "잘못된 시작 태그"오류 및 "잘못된 끝 태그"오류입니다. 이 페이지에서는 발생한 상황, 문제 해결 방법 및 지금 당장 할 수있는 작업을 설명합니다.

이 페이지는 원래 2009 년 3 월에 작성되었습니다. 그 이후로 3.1 시리즈를 대체하는 3.2 시리즈가 출시되었으며 4.x 시리즈의 개발이 진행 중입니다. 이 페이지는 기록 목적으로 유지됩니다.

tl; dr

대신 3.2.0을 사용하십시오.


Pyquery Python에 jQuery 선택기 인터페이스를 제공합니다 (내부에서 lxml 사용).

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

정말 대단합니다. 더 이상 다른 것을 사용하지 않습니다.


요약하자면, lxml는 초고속 프로덕션 품질의 html 및 xml 파서로 자리 잡았으며, soupparserBeautifulSoup의 기능을 대체 하는 모듈 도 포함 합니다. BeautifulSoup는 잘못된 형식의 html 또는 xml에서 데이터를 신속하게 추출하는 시간을 절약하기 위해 설계된 1 인 프로젝트입니다.

lxml 문서에 따르면 두 파서 모두 장단점이 있습니다. 이러한 이유로 lxmlsoupparser앞뒤로 전환 할 수 있도록를 제공 합니다. 인용,

BeautifulSoup은 다른 파싱 접근 방식을 사용합니다. 실제 HTML 파서는 아니지만 정규식을 사용하여 태그 수프를 살펴 봅니다. 따라서 어떤 경우에는 더 관대하고 다른 경우에는 덜 좋습니다. lxml / libxml2가 깨진 HTML을 더 잘 구문 분석하고 수정하는 것은 드문 일이 아니지만 BeautifulSoup은 인코딩 감지에 대한 우수한 지원을 제공합니다. 파서가 더 잘 작동하는 입력에 따라 크게 달라집니다.

결국 그들은 말하고 있습니다.

이 파서를 사용하는 단점 은 lxml의 HTML 파서보다 훨씬 느리다는 것입니다. 따라서 성능이 중요한 경우 특정 경우에 대한 대체 수단으로 만 soupparser를 사용하는 것을 고려할 수 있습니다.

내가 그것들을 올바르게 이해한다면, 그것은 수프 파서가 더 강력하다는 것을 의미합니다 --- 정규 표현식을 사용하여 잘못된 태그의 "수프"를 처리 할 수 ​​있습니다 --- 반면 lxml에 더 간단하고 그냥 파싱하고 트리를 만듭니다. 기대할 것입니다. for 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))

(동일한 출처 : http://lxml.de/elementsoup.html ).

BeautifulSoup의 제작자의 말로 ,

그게 다야! 즐기세요! 나는 모두의 시간을 절약하기 위해 아름다운 수프를 썼다. 익숙해지면 단 몇 분 만에 잘못 설계된 웹 사이트에서 데이터를 엉망으로 만들 수 있습니다. 의견이 있거나 문제가 발생하거나 Beautiful Soup을 사용하는 프로젝트에 대해 알고 싶으면 이메일을 보내주세요.

 --Leonard

Beautiful Soup 문서 에서 인용 .

나는 이것이 이제 명확하기를 바랍니다. The soup는 제대로 디자인되지 않은 웹 사이트에서 데이터를 추출하는 시간을 절약하기 위해 설계된 훌륭한 1 인 프로젝트입니다. 목표는 지금 당장 시간을 절약하고 작업을 완료하는 것입니다. 장기적으로 시간을 절약 할 필요는 없으며 소프트웨어의 성능을 최적화하는 것이 아닙니다.

또한 lxml 웹 사이트 에서

lxml은 Python Package Index에서 2 백만 회 이상 다운로드되었으며 Linux 또는 MacOS-X와 같은 많은 패키지 배포에서 직접 사용할 수도 있습니다.

그리고 왜 lxml에서? ,

C 라이브러리 libxml2 및 libxslt에는 다음과 같은 큰 이점이 있습니다. 표준 준수 ... 모든 기능 ... 빠름. 빠른! 빠른! ... lxml은 libxml2 및 libxslt에 대한 새로운 Python 바인딩입니다.


BeautifulSoup을 사용하지 말고 lxml.soupparser 를 사용하면 lxml의 힘 위에 앉아 정말 깨지고 엉뚱한 HTML을 다루는 BeautifulSoup의 좋은 부분을 사용할 수 있습니다.


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()

For sure i would use EHP. It is faster than lxml, much more elegant and simpler to use.

Check out. 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()    

Output:

Hello world. 

A somewhat outdated speed comparison can be found here, which clearly recommends lxml, as the speed differences seem drastic.

ReferenceURL : https://stackoverflow.com/questions/1922032/parsing-html-in-python-lxml-or-beautifulsoup-which-of-these-is-better-for-wha

반응형