标签?
" />
lxml 的 XMLPullParser 默认按 XML 规则严格解析,但若误用 HTML 解析器(如 et.HTMLParser)或输入内容含不规范的 XHTML/HTML 片段(如缺失根元素、未闭合标签、错误实体),lxml 可能触发“修复模式”,自动包裹文本为 等块级标签。
lxml 的 `xmlpullparser` 默认按 xml 规则严格解析,但若误用 html 解析器(如 `et.htmlparser`)或输入内容含不规范的 xhtml/html 片段(如缺失根元素、未闭合标签、错误实体),lxml 可能触发“修复模式”,自动包裹文本为 `
` 等块级标签。
在你的案例中,输出中大量出现孤立的 <p></p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill8961" title="html-to-pptx-converter"><img
src="https://img.php.cn/upload/skill/000/000/081/179232667384043.jpg" alt="html-to-pptx-converter" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/skill8961" title="html-to-pptx-converter" class="overflowclass">html-to-pptx-converter</a>
<p class="overflowclass">使用 PptxGenJS 和 Python 解析,将结构化的 HTML/CSS 幻灯片内容转换为原生、可编辑的 PowerPoint(.pptx)演示文稿。</p>
</div>
<a rel="nofollow" href="/xiazai/skill8961" title="html-to-pptx-converter" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div> 标签(如 <p> T </p>
<p>></p>),根本原因并非 XMLPullParser 本身行为,而是你实际传入的输入数据被 lxml 当作了 HTML 内容处理——极可能是因为:
-
误用了 HTML 解析器:代码中虽声明
XMLPullParser,但若target或后续处理环节隐式调用了 HTML 模式(例如et.HTMLParser()或et.parse(..., parser=et.HTMLParser())),lxml 会启用 HTML 容错解析,对文本节点进行分段并自动补全块级容器(如<p></p>); -
输入非良构 XML:XHTML 文件若缺少根元素、混用未转义
<code>>、或存在>(缺分号)等非法实体,XMLPullParser会报错;但若实际走的是 HTML 解析路径,则会尝试“修复”——将连续文本按空白和符号边界切分为多个文本节点,并逐个包裹进<p></p>; -
et.tostring(element)输出后又被重新解析:你调用parser.feed(et.tostring(element)),若element原本是 XHTML 片段(如仅<dd>...</dd>),et.tostring()生成的是无根节点的字节流。当该字节流被XMLPullParser解析时,因不符合 XML 单一根规则,解析器可能降级为类 HTML 行为(尤其在某些 lxml 版本或配置下)。
✅ 正确做法是:坚持使用纯 XML 工作流,确保输入为良构 XHTML 文档(有单一根元素、实体完整、标签闭合)。示例修正代码:
from lxml import etree as et
# ✅ 明确使用 XML 解析器(非 HTML)
parser = et.XMLPullParser()
# ✅ 输入必须是合法 XML 字节流:含根元素,实体正确(> 而非 >)
xml_bytes = b'T > 85C : 10ms 85 => T > 30C : 100ms T '
parser.feed(xml_bytes)
parser.close()
# 获取解析后的树
root = parser.close()
print(et.tostring(root, encoding='utf-8', pretty_print=False).decode('utf-8'))
# 输出: T > 85C : 10ms 85 => T > 30C : 100ms T
⚠️ 关键注意事项:
-
不要混用 HTML 和 XML 解析器:XHTML 是 XML 应用,必须用
et.XMLParser()或XMLPullParser,禁用et.HTMLParser(); -
验证输入合法性:用
et.fromstring(xml_bytes)测试是否抛出et.XMLSyntaxError,若有错,先用工具(如xmllint --valid --noout file.xhtml)修复 XHTML; -
实体必须完整:
><code>&等不可省略分号,>是非法的,会导致解析异常或降级; -
避免中间序列化再解析:尽量直接解析原始文件
parser.feed(open('input.xhtml', 'rb').read()),而非tostring → feed,以防编码或结构丢失。
总结:lxml 插入 <p></p> 标签不是“bug”,而是 HTML 容错机制被意外激活的信号。回归 XML 语义、保证输入规范、明确解析器类型,即可彻底避免此类问题。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










