爬虫不止于抓 HTML 页面------许多网站的数据以 JSON 格式通过接口暴露,直接请求接口比解析 HTML 更高效。本文讲清楚如何用开发者工具定位接口、如何处理 JSON 响应,以及常见的接口反爬应对思路。
目录
- 两种爬取思路:HTML 解析 vs 接口请求
- Chrome 开发者工具快速上手
- JSON 数据格式基础
- 用 Python 请求并解析 JSON 接口
- 访问嵌套 JSON 数据
- 接口反爬常见原因与排查
- 结合重试机制的完整示例
①两种爬取思路
爬虫拿数据本质上有两条路:一是下载完整 HTML 页面再用解析库提取目标内容,二是直接请求网站的数据接口(API),拿到结构化的 JSON/XML 数据。
方式 A:GET 整个 HTML→BeautifulSoup / XPath 解析→提取目标字段
方式 B:GET 数据接口→json.loads() 直接转为字典→按键访问
方式 B 更轻量:无需解析 DOM,数据结构清晰,抗页面改版能力强。手机版 H5 页面、新闻聚合类网站几乎都走接口,是找 API 的最佳入口。
②Chrome 开发者工具快速上手
按 F12 或右键"检查"打开开发者工具,定位数据接口主要用以下四个面板:
Elements 查看页面 HTML 结构,用于确认目标内容在 DOM 中的位置和选择器
Network 核心面板。记录所有网络请求,筛选 Fetch/XHR 可快速找到 JSON 接口;Response 标签查看原始返回数据
Console 执行 JS 语句,可用于测试选择器、查看页面变量
Sources 查看页面加载的所有静态资源和 JS 文件,用于分析加密参数的生成逻辑
找接口的标准流程:Network → 刷新页面 → 筛选 Fetch/XHR → 逐条查看 Response,找到返回目标数据的那条请求 → 复制其 Request URL → 在爬虫中直接请求该 URL。
③JSON 数据格式基础
JSON(JavaScript Object Notation)是目前最主流的接口数据格式,结构与 Python 字典/列表高度对应,上手成本很低。
json
{
"code": 200,
"msg": "success",
"data": {
"mydata": {
"name": "张三",
"age": "21",
"tel": "1539324****"
}
}
}
JSON类型 { "key": value } 对象 → Python dict,用键名访问
JSON类型 [ item1, item2 ] 数组 → Python list,用下标访问
JSON类型"字符串" / 123 / true → Python str / int / bool,直接使用
注意 null → None JSON null 对应 Python None,不是字符串 "null"
④用 Python 请求并解析 JSON
requests 提供了两种解析 JSON 响应的方式,推荐使用内置的 .json() 方法,省去手动解码和 json.loads() 的步骤。
python
import requests
import json
url = "https://api.example.com/data"
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/120",
"Referer": "https://www.example.com/" # 部分接口校验来源页面
}
resp = requests.get(url, headers=headers, timeout=5)
# 方式一:手动解码 + json.loads(便于排查编码问题)
content = resp.content.decode("utf-8")
print(type(content)) # <class 'str'>
data = json.loads(content)
print(type(data)) # <class 'dict'>
# 方式二:直接调用 resp.json()(推荐,内部自动处理编码)
data = resp.json()
print(type(data)) # <class 'dict'>
两种方式的核心差异:json.loads() 接收字符串,便于在解析前打印原始内容调试;resp.json() 更简洁,会根据响应头的 Content-Type 自动选择编码,生产代码推荐用后者。
⑤访问嵌套 JSON 数据
JSON 解析后是普通的 Python 字典/列表,支持链式下标访问,也应做好键不存在时的容错处理。
python
import requests
resp = requests.get("https://api.example.com/user", timeout=5)
data = resp.json()
# 示例响应:{"code":200,"data":{"mydata":{"name":"张三","age":"21"}}}
# 逐层访问嵌套字段
print(data["code"]) # 200
print(data["data"]["mydata"]["name"]) # 张三
# 推荐:用 .get() 避免 KeyError,并提供默认值
name = data.get("data", {}).get("mydata", {}).get("name", "未知")
print(name) # 张三(键不存在时返回"未知"而不是报错)
# 如果 data 字段是列表,用下标取元素
# items = data["data"]["list"]
# for item in items:
# print(item["title"])
⑥接口反爬常见原因与排查
直接复制接口 URL 请求时,有时会拿到错误响应而非预期数据。常见原因和对应排查方向:
缺少Referer 服务器校验请求来源页面。在 headers 中加入 "Referer": "来源页URL"
缺少Token 接口要求在 URL 参数或 headers 中携带动态 token。在 Network 面板中检查原始请求的参数
Cookie失效 接口需要登录态。用 Session 模拟登录或从浏览器复制有效 Cookie
IP频率限制 短时间大量请求被封。配合代理池和随机延时降低访问频率
排查时优先对比浏览器原始请求和爬虫请求的 headers 差异(在 Network → 目标请求 → Headers 面板查看)。缺少的字段逐一补上,通常能定位问题。
⑦结合重试机制的完整示例
将 JSON 接口请求与上一篇介绍的重试机制结合,构建一个鲁棒的接口爬取函数:
python
import requests
from retrying import retry
@retry(stop_max_attempt_number=3, wait_fixed=2000)
def fetch_json(url, extra_headers=None):
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/120",
"Accept": "application/json, text/plain, */*",
}
if extra_headers:
headers.update(extra_headers)
resp = requests.get(url, headers=headers, timeout=5)
resp.raise_for_status() # 4xx/5xx 触发重试
data = resp.json()
# 业务层校验:接口返回 code 非成功时同样重试
if data.get("code") != 200:
raise ValueError(f"接口错误:{data.get('msg')}")
return data
def main():
api_url = "https://api.example.com/user"
extra = {"Referer": "https://www.example.com/"}
try:
result = fetch_json(api_url, extra)
name = result.get("data", {}).get("mydata", {}).get("name")
print(f"姓名:{name}")
except Exception as e:
print(f"请求最终失败:{e}")
if __name__ == "__main__":
main()
注意业务层和 HTTP 层的双重校验:raise_for_status() 处理 HTTP 状态码异常,而业务 code 校验(如 code != 200)处理接口自定义的错误码------两者缺一不可。
✓小结
定位接口 Network → XHR
解析JSON resp.json()
安全取值 .get() 链式
接口反爬 补齐Headers
容错 重试+双重校验
直接请求 JSON 接口是比解析 HTML 更高效的爬取方式,适用于大多数现代 Web 应用。掌握开发者工具 Network 面板的使用、JSON 结构的访问方式,以及接口反爬的排查思路,是爬虫进阶的核心技能。下一篇将介绍 BeautifulSoup 对 HTML 内容的结构化解析。