Python 如何防止lxml添加默认doctype

Python 如何防止lxml添加默认doctype,python,lxml,libxml2,Python,Lxml,Libxml2,当html文档中缺少一个doctype时,lxml似乎会添加一个默认doctype 请参阅此演示代码: import lxml.etree import lxml.html def beautify(html): parser = lxml.etree.HTMLParser( strip_cdata=True, remove_blank_text=True ) d = lxml.html.fromstring(html, parser

当html文档中缺少一个doctype时,lxml似乎会添加一个默认doctype

请参阅此演示代码:

import lxml.etree
import lxml.html


def beautify(html):
    parser = lxml.etree.HTMLParser(
        strip_cdata=True,
        remove_blank_text=True
    )

    d = lxml.html.fromstring(html, parser=parser)
    docinfo = d.getroottree().docinfo

    return lxml.etree.tostring(
        d,
        pretty_print=True,
        doctype=docinfo.doctype,
        encoding='utf8'
    )


with_doctype = """
<!DOCTYPE html>
<html>
<head>
  <title>With Doctype</title>
</head>
</html>
"""

# This passes!
assert "DOCTYPE" in beautify(with_doctype)

no_doctype = """<html>
<head>
  <title>No Doctype</title>
</head>
</html>"""

# This fails!
assert "DOCTYPE" not in beautify(no_doctype)

# because the returned html contains this line
# <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
# which was not present in the source before
导入lxml.etree
导入lxml.html
def美化(html):
parser=lxml.etree.HTMLParser(
strip\u cdata=True,
删除\u blank\u text=True
)
d=lxml.html.fromstring(html,parser=parser)
docinfo=d.getroottree().docinfo
返回lxml.etree.tostring(
D
漂亮的印刷品=真的,
doctype=docinfo.doctype,
编码='utf8'
)
使用“doctype=”“”
带Doctype
"""
#这就过去了!
在美化中断言“DOCTYPE”(使用_DOCTYPE)
否_doctype=“”
没有Doctype
"""
#这失败了!
断言“DOCTYPE”不在美化中(无DOCTYPE)
#因为返回的html包含这一行
# 
#这在以前的资料中是不存在的

我如何告诉lxml不要这样做

这个问题最初是在这里提出的:

引用可能有帮助的答案:

lxml是基于libxml2的,默认情况下它会这样做,除非您传递选项
HTML\u PARSE\u NODEFDTD
。代码

我不知道您是否可以告诉lxml通过该选项。。libxml有python绑定,您可能可以直接使用它们,但它们看起来非常复杂

编辑:进行了更多的挖掘,该选项确实出现在lxml资源中。这个选项正是你想要的,但我还不确定如何激活它,如果可能的话


目前在lxml中没有办法做到这一点,但我已经创建了一个,它在
HTMLParser
中添加了一个
default\u doctype
布尔值

一旦代码被合并,就需要像这样创建解析器:

parser = lxml.etree.HTMLParser(
    strip_cdata=True,
    remove_blank_text=True,
    default_doctype=False,
)

其他一切都保持不变。

中没有处理
HTML\u PARSE\u NODEFDTD
选项,因此您可能运气不好。@nwellnhof也许我们可以解决这个问题,并创建一个PR@lxml?不过,这个选项是存在的。我也是。目前还没有解决方案。FWIW,libxml2 Perl绑定,也是。我认为解决这个问题不会太难,但我只是没有足够的cython等方面的经验。所以我自己无法编译它。