用tree.xpath("//a/@href")最稳,可跳过无效嵌套、自闭合标签及混排子元素;需注意勿误写为text()或漏@符号,且href可能为相对路径、需手动处理base标签或js渲染内容。

lxml解析HTML后怎么提取所有a标签的href属性
直接用tree.xpath("//a/@href")最稳,比findall()或cssselect()更可靠。XPath能跳过无效嵌套、自闭合伪标签,也不怕a里混着span或img。
常见错误是写成tree.xpath("//a/text()")——那取的是链接文字,不是地址;或者漏了@,写成"//a/href",结果返回空列表。
- 确保传入的是
etree.HTML()解析后的树对象,不是原始字符串 -
href值可能是相对路径(如"./page.html")、协议相对(如"//example.com/path")或空字符串,需后续标准化 - 如果页面用了
base[href]标签,lxml不会自动解析相对路径,得手动处理
遇到JavaScript渲染的链接,lxml为什么完全抓不到
lxml只处理静态HTML源码,不执行JS。如果链接由fetch()、Vue.mount()或document.write()动态插入,源码里压根没有a标签,xpath自然返回空。
典型现象:浏览器F12看到链接,但requests.get(url).text里搜不到<a href="</code">;或者用<code>curl -s URL | grep "<a>也无结果。</a>
- 先用
curl -s URL | head -30确认源码是否含目标a标签 - 真要抓JS渲染内容,得换
playwright或selenium,lxml不负责这事 - 部分站点用
data-url或ng-href存地址,可扩展xpath为"//a/@href | //a/@data-url | //a/@ng-href"
lxml提取的链接带特殊字符或乱码怎么办
本质是HTML编码没解对,比如href="page%20name.html"或href="测试.html"在源码中被编码为%E6%B5%8B%E8%AF%95.html,但lxml默认不自动解码。
错误做法是直接用urllib.parse.unquote()硬解——可能把本就合法的%2F(即/)错解成路径分隔符,破坏URL结构。
- 只对
href中非标准ASCII部分用urllib.parse.unquote(),且限定在路径段(不碰协议、域名) - 更稳妥的做法:先用
urllib.parse.urlparse()拆解,对path和query分别unquote(),再拼回去 - 若原始HTML声明了
<meta charset="gb2312">浣
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











