【发布时间】:2021-10-02 19:00:46
【问题描述】:
这是一些 HTML:
<ol><ul><li>item</li></ul></ol>
还有一些带有lxml 的python 3 代码来解析它并重新打印它:
import sys
from lxml import etree, html
document_root = html.fromstring(sys.stdin.read())
print(etree.tostring(document_root, encoding='unicode'))
这是输出:
<div><ol/><ul><li>item</li></ul>
</div>
在输出中,lxml 在ul 开始之前关闭ol,这会改变列表结构。
为什么要这么做?
我能否让lxml 以保留列表结构的方式解析 HTML?
编辑:请注意,如果我将 ul 替换为 ol (<ol><ol><li>item</li></ol></ol>),或者将 ol 替换为 ul (<ul><ul><li>item</li></ul></ul>),则此示例解析良好.输出与输入保持不变。
我无法控制 HTML,它可能来自任何地方。
我使用的是从 PyPi 安装的 lxml 4.6.3 和 python 3.9。
或者,是否有另一种方法来解析 HTML,以便我可以从中提取列表文本并保留 Python 中的列表结构?
您知道,我正在使用 lxml 删除属性,所以下面的代码更接近我的用例。但是,我想先给出最小的可重现测试用例。
代码更接近我的用例:
import sys
import lxml.html.clean as clean
from lxml import etree, html
document_root = html.fromstring(sys.stdin.read())
cleaner = clean.Cleaner(safe_attrs_only=True, safe_attrs=frozenset())
cleansed = cleaner.clean_html(document_root)
# Do something with the lists in cleansed, defined by ol, ul, and li ..
print(etree.tostring(cleansed, encoding='unicode')
【问题讨论】:
-
无法解释原因,但似乎只有
html有问题。它似乎适用于document_root = etree.fromstring(sys.stdin.read())。 -
也许这对我来说是一件值得尝试的事情。我认为 html 对来自世界上可能格式不太好的 html 片段更有弹性,但也许更大的威胁是 lxml 破坏了格式良好的 html。
-
“也许更大的威胁是 lxml 破坏格式良好的 html” - 是的,它也困扰着我;不记得曾经遇到过这种情况,这令人担忧。让我们希望 lxml 的权力之一注意到这一点并解决这个问题。
-
我认为 HTML 4 和 HTML5 都不允许
ul元素作为ol元素的子元素,这可能是 HTML 解析器构建不代表嵌套的树结构的部分原因你有你的输入标记。一个“传统的”HTML 4 解析器,比如可能在 lxml/libxml 的 HTML 解析器算法中实现的,是否对结构做了同样的改变,我不记得了,我不知道在哪里测试它。虽然两个 HTML5 验证器清楚地将您的ul标记为ol的不允许子级,但当前浏览器似乎保留了这种嵌套。 -
我也认为问题出在
ul作为ol的孩子。类似问题:stackoverflow.com/q/44976672/407651.
标签: html-parsing lxml