lxml是python中解析html并执行xpath查询的首选第三方库,安装命令为pip install lxml;推荐用etree.html()加载html字符串以兼容不规范标签,再用.xpath()方法执行查询,属性需用@前缀(如//a/@href),返回值恒为list,需索引或安全取值。

用 lxml 解析 HTML 并执行 XPath 查询
Python 标准库不支持 XPath,必须借助第三方库。最稳定、兼容性最好、性能也够用的是 lxml。它能正确处理 malformed HTML(比如缺失闭合标签),比 BeautifulSoup + lxml 解析器更轻量、更直接。
安装命令是:pip install lxml。注意:Windows 用户如果遇到编译错误,建议用 pip install lxml --only-binary=lxml 避免源码编译。
基本流程是:先用 lxml.html.fromstring() 或 lxml.etree.fromstring() 加载 HTML 字符串(后者要求严格 XML 格式,普通 HTML 推荐前者);再调用 .xpath() 方法传入 XPath 表达式。
提取特定属性值的 XPath 写法和常见错误
想取某个元素的 href、src、data-id 等属性,XPath 必须显式用 @ 前缀。比如 //a/@href 返回所有 <a></a> 的 href 值列表,而不是元素本身。
- 错误写法:
//img/src→ 这会匹配名为src的子元素,不是src属性 - 正确写法:
//img/@src - 带条件时注意括号优先级:
//div[@class="card"]//button[@type="submit"]/@data-value - 如果属性名含连字符(如
data-track-id),XPath 中照写即可,无需转义
返回值是 Python list,即使只匹配一个元素——这点容易忽略,后续取值要加索引或用 next(iter(...), None) 安全获取首项。
xpath() 返回空列表的几个典型原因
查不到值不一定是 XPath 写错,更可能是解析上下文或 HTML 结构问题:
- HTML 被 JavaScript 动态渲染(比如单页应用)→
lxml只解析静态 HTML,需换用Selenium或Playwright先渲染 - 目标元素在
<iframe></iframe>里 →lxml不跨 frame 解析,得单独请求 iframe 的 src 地址 - HTML 编码不一致(如 GBK 页面没声明编码)→ 解析时乱码导致标签名失配,用
fromstring(html.encode("utf-8"))强制转码 - XPath 匹配了元素但属性不存在 →
//div/@data-id在没有data-id的<div> 上返回空,不是报错 <p>调试建议:先用 <code>tree.xpath("//body")[0].text_content()[:200]确认解析是否成功;再逐步缩短 XPath(比如从//div[@class]开始)验证路径有效性。处理命名空间和 HTML5 自定义属性的细节
多数网页不需要声明命名空间,但若 HTML 含
xmlns(比如某些 RSS 或 XHTML 混合页面),直接写 XPath 会失败。此时需传入namespaces参数:tree.xpath('//xhtml:div/@class', namespaces={'xhtml': 'http://www.w3.org/1999/xhtml'})对 HTML5 的
data-*属性(如data-product-id),XPath 完全支持,无需特殊处理。但注意大小写敏感:HTML 属性名本身不区分大小写,而lxml解析后按原始大小写存储,所以@DATA-ID和@data-id是不同的。另外,
xpath()默认返回字符串或lxml.etree._ElementUnicodeResult对象,可直接当str用,但别假设它是原生str——做isinstance(x, str)判断可能为False,稳妥做法是显式调用str(x)。











