本文介绍了为什么lxml在解析时关闭这个&q;ol&q;标记?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下是一些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?

edit:请注意,如果我将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')

推荐答案

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

这可能就是HTML解析器构建不表示输入标记中的嵌套的树结构的原因。传统的HTML 4解析器(可能是在lxml的/libxml的HTML解析器算法中实现的)是否对结构进行了相同的更改,我不记得了,我也不确定在哪里测试它。

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

这篇关于为什么lxml在解析时关闭这个&q;ol&q;标记?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

05-17 20:12