Python 爬虫 XPath 定位语法详解与实战
XPath(XML Path Language)是 Python 爬虫过程中非常重要的一种用来定位网页元素的语法。它通过路径表达式在 HTML 或 XML 文档树中查找节点,包括元素、属性、文本内容等。本文将详细介绍 XPath 的基础语法、常用函数以及在实际爬虫项目中的应用。
1. 环境准备
在使用 XPath 之前,需要安装 lxml 库,它是 Python 中最常用的 XML/HTML 解析库之一,支持 XPath 1.0 标准。
本文详细介绍了 Python 爬虫中 XPath 定位语法的用法。内容包括环境配置、基础路径表达式、谓语筛选、模糊匹配函数(contains、starts-with)、文本与属性获取方法。通过豆瓣电影 Top250 的实战案例,展示了如何结合 requests 库进行完整的数据抓取流程,并提供了关于反爬策略、容错处理和性能优化的最佳实践建议。

XPath(XML Path Language)是 Python 爬虫过程中非常重要的一种用来定位网页元素的语法。它通过路径表达式在 HTML 或 XML 文档树中查找节点,包括元素、属性、文本内容等。本文将详细介绍 XPath 的基础语法、常用函数以及在实际爬虫项目中的应用。
在使用 XPath 之前,需要安装 lxml 库,它是 Python 中最常用的 XML/HTML 解析库之一,支持 XPath 1.0 标准。
pip install lxml
同时,爬虫通常还需要 requests 库来获取网页内容:
pip install requests
XPath 的核心思想是通过路径表达去寻找节点。节点包括元素、属性和内容。
| 符号 | 含义 |
|---|---|
/ | 根节点,节点分隔符 |
// | 任意位置(递归下降) |
. | 当前节点 |
.. | 父级节点 |
@ | 属性 |
* | 通配符,匹配任意元素 |
示例代码:
from lxml import etree
doc = '''
<div>
<ul>
<li class="item-0"><a href="link1.html">first item</a></li>
<li class="item-1"><a href="link2.html">second item</a></li>
<li class="item-inactive"><a href="link3.html">third item</a></li>
</ul>
</div>
'''
html = etree.HTML(doc)
# 获取所有 li 元素
print(html.xpath("//li"))
# 获取 div 下的第一个 ul
print(html.xpath("/div/ul[1]"))
# 获取当前节点的父节点
print(html.xpath("//li[@class='item-0']/.."))
使用中括号 [] 来限定元素,称为谓语。这允许我们根据索引、属性值或特定条件筛选节点。
# 选取第 n 个 a 元素(从 1 开始计数)
//a[n]
# 选取最后一个 a 元素
//a[last()]
# 选取倒数第二个 a 元素
//a[last()-1]
# 选取位置序号小于 3 的元素(即前两个)
//a[position()<3]
# 选取拥有 href 属性的 a 元素
//a[@href]
# 选取 href 属性值为 'www.baidu.com' 的 a 元素
//a[@href='www.baidu.com']
# 选取 price 值大于 2 的 book 元素
//book[@price>2]
当网页样式发生变化时,class 属性可能会增加或减少。使用完全匹配 @class='...' 可能失效,此时可以使用 contains() 或 starts-with() 函数。
from lxml import etree
doc = '''
<div>
<ul>
<p class="item-0 active"><a href="link1.html">first item</a></p>
<li class="item-1"><a href="link2.html">second item</a></li>
<li class="item-inactive"><a href="link3.html">third item</a></li>
</ul>
</div>
'''
html = etree.HTML(doc)
# 匹配 class 包含 'item' 的所有元素
print(html.xpath("//*[contains(@class,'item')]")
# 匹配 class 以 'ul' 开头的元素
print(html.xpath("//*[starts-with(@class,'ul')]")
可以使用 .text 属性或 text() 函数来获取元素的内容。
# 获取所有 a 标签的文本列表
print(html.xpath("//a/text()"))
# 获取第一个 a 标签的文本
print(html.xpath("//a")[0].text)
# 获取 ul 标签内的直接文本(注意:如果文本在子标签内,这里可能为空)
print(html.xpath("//ul")[0].text)
使用 @ 符号配合 xpath 方法可以获取属性值。
# 获取所有 a 标签的 href 属性
print(html.xpath("//a/@href"))
# 获取所有 li 标签的 class 属性
print(html.xpath("//li/@class"))
下面是一个完整的示例,展示如何使用 requests 获取页面,结合 lxml 和 XPath 解析数据。
import requests
from lxml import etree
import time
def main():
# 设置请求头,模拟浏览器访问
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36"
}
baseurl = "https://movie.douban.com/top250?start="
movie_list = []
for i in range(0, 250, 25): # 每次抓取 25 条,共 10 页
url = f"{baseurl}{i}"
try:
res = requests.get(url=url, headers=headers, timeout=10).text
data = etree.HTML(res)
# 定位每一部电影条目
items = data.xpath('//*[@id="content"]/div/div[1]/ol/li')
for item in items:
video_info = {
"title": "",
"year": "",
"score": 0,
"num": 0
}
# 提取标题
title_list = item.xpath('./div/div[2]/div[1]/a/span/text()')
for text_item in title_list:
video_info['title'] += text_item.replace("\n", "").replace("\xa0", " ")
# 提取年份
year_text = item.xpath('./div/div[2]/div[2]/p[1]/text()')[1].split("/")[0]
video_info['year'] = year_text.replace("\n", "").replace("\xa0", " ").strip()
# 提取评分
score_text = item.xpath('./div/div[2]/div[2]/div/span[2]/text()')[0]
video_info['score'] = score_text
# 提取评价人数
num_text = item.xpath('./div/div[2]/div[2]/div/span[4]/text()')[0]
video_info['num'] = num_text.replace("人评价", "")
movie_list.append(video_info)
print(f"已抓取第 {i // 25 + 1} 页数据")
time.sleep(1) # 礼貌性延迟,避免被封 IP
except Exception as e:
print(f"抓取失败:{e}")
continue
return movie_list
if __name__ == '__main__':
movies = main()
for m in movies[:5]:
print(m)
// 而不是 /,除非确定层级关系;对于大量数据抓取,建议分批处理。User-Agent,并在请求之间加入随机延时,避免触发目标网站的反爬机制。utf-8),防止中文乱码。XPath 是 Python 爬虫中强大的定位工具。掌握其基础语法、谓词筛选以及常用函数,能够高效地提取网页中的结构化数据。在实际开发中,结合 lxml 和 requests 库,并注意网络请求的规范性,可以构建稳定可靠的爬虫程序。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online
通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online