是否有一个内置的包来将 html 解析为 dom?

问题描述 投票:0回答:5

我发现

HTMLParser
用于 SAX 和
xml.minidom
用于 XML。我有一个格式很好的 HTML,所以我不需要太强大的解析器 - 有什么建议吗?

python html dom parsing
5个回答
29
投票

我会推荐lxml。我喜欢 BeautifulSoup,但通常存在维护问题以及与更高版本的兼容性问题。我一直很高兴使用 lxml。


后期:最好推荐使用lxml、html5lib或者BeautifulSoup 3.0.8。 BeautifulSoup 3.1.x 适用于 python 3.x,并且已知在较早的 python 版本中存在问题,如 BeautifulSoup 网站上所述

Ian Bicking 有一篇关于使用 lxml 的好文章

ElementTree是进一步推荐,但我没用过


2012-01-18:有人过来并决定对我和 Bartosz 投反对票,因为我们推荐的 python 包很容易获得,但不是 python 发行版的一部分。所以对于高度文字化的 StackOverflowers:“你可以使用 xml.dom.minidom,但没有人会推荐这个替代品。”


20
投票

BeautifulSoup 和 lxml 很棒,但这里不是合适的答案,因为问题是关于内置的。下面是一个使用内置 minidom 模块解析 HTML 字符串的示例。使用 cPython 3.5.2 测试:

from xml.dom.minidom import parseString

html_string = """
<!DOCTYPE html>
<html><head><title>title</title></head><body><p>test</p></body></html>
"""

# extract the text value of the document's <p> tag:
doc = parseString(html_string)
paragraph = doc.getElementsByTagName("p")[0]
content = paragraph.firstChild.data

print(content)

但是,如 Jesse Hogan 的 comment 所示,这将在 mindom 无法识别的 HTML 实体上失败。这是使用 Python3 html.parser 模块的更新解决方案:

from html.parser import HTMLParser

html_string = """
<!DOCTYPE html>
<html><head><title>title</title></head><body><p>&nbsp;test</p><div>not in p</div></body></html>
"""

class Parser(HTMLParser):
    def __init__(self):
        HTMLParser.__init__(self)
        self.in_p = []

    def handle_starttag(self, tag, attrs):
        if (tag == 'p'):
            self.in_p.append(tag)

    def handle_endtag(self, tag):
        if (tag == 'p'):
            self.in_p.pop()

    def handle_data(self, data):
        if self.in_p:
            print("<p> data :", data)

parser = Parser()
parser.feed(html_string)

16
投票

看看BeautifulSoup。它很受欢迎,并且擅长解析 HTML。


3
投票

要处理 DOM 对象,您可以使用 HTMLDOM for python。


0
投票

有一个技巧只使用 python3 内置函数 (3.4+)

使用

html.unescape
解码所有html5实体。 然后使用
html.escape
<>"&
编码回 xml 解析器的实体,将其他实体保留为字符串中的 unicode 字符。

#! /usr/bin/python3
import re
import xml.dom.minidom
from html import escape, unescape

def minidom_parseHtml(text: str):
     "parse html text with non-xml html-entities as minidom"
     textXML = re.sub("\\&\\w+\\;", lambda x: escape(unescape(x.group(0))), text)
     return xml.dom.minidom.parseString(textXML)
© www.soinside.com 2019 - 2024. All rights reserved.