【问题标题】:Why is lxml closing this "ol" tag when parsing?为什么lxml在解析时会关闭这个“ol”标签?
【发布时间】: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>

在输出中,lxmlul 开始之前关闭ol,这会改变列表结构。

为什么要这么做?

我能否让lxml 以保留列表结构的方式解析 HTML?

编辑:请注意,如果我将 ul 替换为 ol (&lt;ol&gt;&lt;ol&gt;&lt;li&gt;item&lt;/li&gt;&lt;/ol&gt;&lt;/ol&gt;),或者将 ol 替换为 ul (&lt;ul&gt;&lt;ul&gt;&lt;li&gt;item&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;),则此示例解析良好.输出与输入保持不变。

我无法控制 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


【解决方案1】:

我认为 HTML 4 和 HTML5 都不允许 ul 元素作为 ol 元素的子元素。只有li 元素可以是直接子元素。

这可能就是为什么 HTML 解析器构建一个不代表您在输入标记中的嵌套的树结构的原因。一个“传统的”HTML 4 解析器,比如可能在 lxml's/libxml 的 HTML 解析器算法中实现的,是否对结构做了同样的改变,我不记得了,我不知道在哪里测试它。

虽然两个 HTML5 验证器将您的 ul 标记为 ol 的不允许子级,但当前的浏览器似乎保留了这种嵌套。

【讨论】:

    猜你喜欢
    • 2018-10-23
    • 1970-01-01
    • 2021-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-13
    相关资源
    最近更新 更多