XPath从入门到实战:掌握网页数据提取与元素定位的终极指南(附Python代码)

一、XPath 核心概念

XPath(XML Path Language) 是一种用于在 XML/HTML 文档中定位节点的查询语言,通过路径表达式精准定位元素,支持属性过滤、文本提取和函数计算。
应用场景:网页爬虫、自动化测试(Selenium)、XML 数据解析。


二、Python 环境配置

安装依赖库
pip install lxml requests  # 基础解析库
pip install selenium       # 动态页面支持
解析文档的三种方式
from lxml import etree

# 1. 解析本地文件
tree = etree.parse('demo.html')

# 2. 解析字符串
html_str = "<div><p>Hello</p></div>"
tree = etree.HTML(html_str)

# 3. 解析网络请求
import requests
response = requests.get('https://example.com')
tree = etree.HTML(response.content)  # 推荐使用 content 避免编码问题

三、XPath 语法详解(附 Python 代码)

1. 节点定位
表达式说明Python 代码示例输出
//a所有 <a> 标签tree.xpath('//a/text()')链接文本列表
/html/body根节点下的绝对路径tree.xpath('/html/body/div')body 下的 div 节点
.//span当前节点下的所有 spandiv_element.xpath('.//span')span 列表
//a/@href提取 href 属性tree.xpath('//a/@href')链接地址列表
2. 属性过滤
# 精确匹配属性
tree.xpath('//input[@id="search"]')  # id 为 search 的输入框

# 模糊匹配(动态属性)
tree.xpath('//div[contains(@class, "nav")]')   # class 包含 "nav"
tree.xpath('//a[starts-with(@href, "https")]') # href 以 https 开头

# 多属性组合
tree.xpath('//input[@type="text" and @name="user"]')
3. 文本提取
# 获取直接文本(可能含空白)
tree.xpath('//p/text()')  # 返回文本列表(含换行符)

# 获取节点内所有文本(规范化)
tree.xpath('string(//div)')  # 返回合并后的连续文本

# 按文本内容筛选节点
tree.xpath('//a[text()="登录"]')      # 精确匹配
tree.xpath('//div[contains(text(), "热门")]') # 模糊匹配
4. 函数与轴定位
# 常用函数
tree.xpath('count(//li)')        # 统计节点数量
tree.xpath('//book[price>30]')   # 价格大于 30 的书

# 轴定位(父子/兄弟关系)
tree.xpath('//div/child::p')              # 子节点 <p>
tree.xpath('//span/parent::div')           # 父节点 <div>
tree.xpath('//td[text()="价格"]/following-sibling::td')  # 右侧相邻单元格

四、Python 实战:爬取小说章节

目标网站结构示例
<div class="cate-list">
  <ul>
    <li>
      <a href="/chapter/1.html">第一章 北灵院</a>
      <a href="/chapter/2.html">第二章 被踢出灵路的少年</a>
    </li>
  </ul>
</div>
完整代码
import requests
from lxml import etree

url = 'http://book.example.com/novel.html'
headers = {'User-Agent': 'Mozilla/5.0'}

response = requests.get(url, headers=headers)
response.encoding = 'utf-8'  # 解决中文乱码
tree = etree.HTML(response.text)

# 定位所有章节链接和标题
chapters = tree.xpath('//div[@class="cate-list"]/ul/li/a')
for chap in chapters:
    title = chap.xpath('string(.)')  # 获取标签内完整文本
    link = chap.xpath('@href')[0]
    print(f"{title}: {link}")

# 输出示例:
# 第一章 北灵院: /chapter/1.html
# 第二章 被踢出灵路的少年: /chapter/2.html

五、注意事项

  1. 动态属性陷阱
    避免使用 //div[@id="js-123"](数字会变),改用模糊匹配:
    //div[contains(@id, "js-")]

  2. 跨框架定位失效
    在 Selenium 中需切换 iframe:

    driver.switch_to.frame("frame_name")
    element = driver.find_element(By.XPATH, '//button')
    
  3. 性能优化策略

    • 优先用 ID 或稳定属性(比 class 快 10 倍)
    • 减少 // 使用范围:div_element.xpath('.//p')
    • 编译复用表达式:
      get_links = etree.XPath('//a/@href')
      links = get_links(tree)
      
  4. 浏览器复制路径不可靠
    浏览器生成的 XPath 可能冗长(如 /html/body/div[2]/div[5]/span),需优化为语义化路径。


六、XPath vs CSS 选择器

特性XPathCSS 选择器
父节点定位✅ 支持(..parent::❌ 不支持
文本节点筛选//a[text()="登录"]❌ 不支持
函数支持contains(), starts-with⚠️ 部分伪类(如:contains
浏览器原生支持⚠️ 需 document.evaluate✅ 主流支持

七、总结

最佳实践

  1. 优先使用 iddata- 等稳定属性;
  2. 动态内容用 contains()starts-with() 处理;
  3. 复杂文档用轴定位提高精度;
  4. 调试工具推荐 Chrome 插件 XPath Helper 或控制台 $x('//xpath')
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值