You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何不使用正则移除HTML无匹配闭合标签?解决lxml解析异常

修复无效HTML结构,让lxml正确解析

先看你给出的这段有问题的HTML:

<li class='item'> 
  <ul class="lvprices left space-zero" _sp="p2045573.m1686.l8"> 
    <li class="lvshipping"> 
      <span class="ship"> 
        <span> 
          <span class="bfsp">Free Shipping</span> 
        </span> 
      </span> 
    </li> 
  </li> <!-- 这里的多余</li>是**罪魁祸首** -->
  </ul> 
  <ul class=""> 
    <li class="timeleft"> 
      <span class="tme"> 
        <span>May-25 01:57</span> 
      </span> 
    </li> 
  </ul> 
</li>

你说的问题确实很典型——这个无匹配的</li>直接打乱了lxml的解析逻辑,导致第二个<ul>被排除在class="item"的<li>之外。不用正则的话,其实可以靠遵循HTML5标准的解析器自动修复这个结构,给你两种可行的方法:

方法1:用BeautifulSoup + html5lib修复

你之前试过BeautifulSoup但没解决,应该是用了默认的html.parser,换成html5lib就行,它会完全模拟浏览器的解析规则,自动处理这类无效标签:

首先确保装了html5lib:

pip install html5lib

然后写代码:

from bs4 import BeautifulSoup
from lxml import etree

# 你的原始HTML文本
raw_html = """<li class='item'> <ul class="lvprices left space-zero" _sp="p2045573.m1686.l8"> <li class="lvshipping"> <span class="ship"> <span> <span class="bfsp">Free Shipping</span> </span> </span> </li> </li> </ul> <ul class=""> <li class="timeleft"> <span class="tme"> <span>May-25 01:57</span> </span> </li> </ul> </li>"""

# 用html5lib解析并修复结构
soup = BeautifulSoup(raw_html, "html5lib")
fixed_html = str(soup)

# 现在用lxml解析修复后的HTML,XPath就能正常工作了
tree = etree.HTML(fixed_html)
target_uls = tree.xpath("//li[@class='item']/ul")
print(f"成功找到 {len(target_uls)} 个<ul>元素")  # 应该输出2

方法2:直接用lxml的html5解析器

如果不想依赖BeautifulSoup,也可以用lxml自带的html5解析模块(需要安装lxml的html5扩展):

先安装依赖:

pip install lxml[html5]

然后代码更简洁:

from lxml.html import html5parser

raw_html = """<li class='item'> <ul class="lvprices left space-zero" _sp="p2045573.m1686.l8"> <li class="lvshipping"> <span class="ship"> <span> <span class="bfsp">Free Shipping</span> </span> </span> </li> </li> </ul> <ul class=""> <li class="timeleft"> <span class="tme"> <span>May-25 01:57</span> </span> </li> </ul> </li>"""

# 用html5parser直接解析,自动修复结构
tree = html5parser.fromstring(raw_html)
target_uls = tree.xpath("//li[@class='item']/ul")
print(f"成功找到 {len(target_uls)} 个<ul>元素")  # 同样输出2

这两种方法的核心都是让专业的HTML5解析器来处理无效标签,它们会自动移除那个多余的</li>,重建正确的DOM结构,这样lxml的XPath就能正常遍历到所有子元素了。

内容的提问来源于stack exchange,提问作者Gorlan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 06:56:12