4. API请求实战(一):使用requests库发送GET请求、解析JSON响应、处理分页数据、错误处理与重试机制
各位同学,今天咱们来点真家伙。
前面几章我们把API的基础概念、认证方式、数据格式都捋了一遍。说实话,光看不练那是纸上谈兵。从这一章开始,我们要真正动手写代码了。
我个人习惯,学任何技术都是先跑通一个最简单的例子,然后再往里面加东西。今天我们就用Python的requests库,把风电数据API调通。你想想看,一个风机每天产生成千上万条数据,没有API你怎么拿?
4.1 准备工作:安装与导入
首先,你得确保requests库已经装好了。我见过不少新手卡在这一步,其实很简单:
pip install requests
装好之后,在代码里导入:
import requests
import json
from time import sleep
嗯,这里要注意,json库是Python自带的,用来处理JSON数据。sleep后面我们会用到,做重试的时候用得上。
4.2 发送第一个GET请求
好,我们直接上代码。假设我们要从一个风电数据平台获取某台风机的实时功率数据:
url = "https://api.windfarm.com/v1/turbines/WT001/realtime"
headers = {
"Authorization": "Bearer your_token_here",
"Content-Type": "application/json"
}
response = requests.get(url, headers=headers)
print(response.status_code)
print(response.text)
跑一下,如果看到200,恭喜你,通了。
201而不是200,这其实也是成功。别死盯着200不放。
4.3 解析JSON响应
拿到数据之后,它是一段JSON字符串。我们需要把它解析成Python能用的字典或列表。
if response.status_code == 200:
data = response.json()
print(data)
else:
print(f"请求失败,状态码:{response.status_code}")
response.json()这个方法,说白了就是把JSON字符串转成Python对象。你看,多简单。
假设返回的数据长这样:
{
"turbine_id": "WT001",
"timestamp": "2025-03-15T10:30:00Z",
"power_kw": 1850.5,
"wind_speed_mps": 12.3,
"status": "running"
}
那我们就可以这样取值:
power = data["power_kw"]
wind_speed = data["wind_speed_mps"]
print(f"当前功率:{power} kW,风速:{wind_speed} m/s")
KeyError。我建议用data.get("power_kw", 0),这样更安全。
4.4 处理分页数据
这才是今天的重头戏。
你想想看,一个风场几十台风机,每台风机每秒一条数据,一天下来数据量有多大?API不可能一次性全给你,所以就有了分页。
常见的分页方式有两种:
| 分页方式 | 说明 | 示例参数 |
|---|---|---|
| 基于页码 | 通过page和page_size控制 |
?page=1&page_size=100 |
| 基于游标 | 通过cursor或offset控制 |
?cursor=abc123&limit=100 |
我个人习惯用基于页码的方式,逻辑更直观。下面是一个完整的例子:
def fetch_all_turbine_data(base_url, headers, page_size=100):
all_data = []
page = 1
total_pages = None
while True:
params = {
"page": page,
"page_size": page_size
}
response = requests.get(base_url, headers=headers, params=params)
if response.status_code != 200:
print(f"第{page}页请求失败")
break
data = response.json()
all_data.extend(data["results"])
# 第一次请求时获取总页数
if total_pages is None:
total_pages = data["total_pages"]
print(f"共{total_pages}页数据")
print(f"已获取第{page}页,共{len(data['results'])}条")
if page >= total_pages:
break
page += 1
return all_data
你看,逻辑其实很简单:先请求第一页,拿到总页数,然后一页一页往下翻,直到翻完。
total_pages是动态变化的。因为数据在不断新增,你翻到后面几页时,总页数可能已经变了。解决办法是:要么用游标分页,要么在循环里每次都重新获取总页数。
4.5 错误处理与重试机制
网络请求这东西,说白了就是不可靠的。服务器可能挂了,网络可能断了,token可能过期了。所以,错误处理和重试机制是必须的。
我一般会写一个带重试的请求函数:
def request_with_retry(url, headers, max_retries=3, delay=2):
for attempt in range(1, max_retries + 1):
try:
response = requests.get(url, headers=headers, timeout=10)
if response.status_code == 200:
return response.json()
elif response.status_code == 429:
print(f"请求太频繁,等待{delay}秒后重试...")
sleep(delay)
elif response.status_code == 500:
print(f"服务器错误,第{attempt}次重试...")
sleep(delay)
else:
print(f"未知错误,状态码:{response.status_code}")
return None
except requests.exceptions.Timeout:
print(f"请求超时,第{attempt}次重试...")
sleep(delay)
except requests.exceptions.ConnectionError:
print(f"连接失败,第{attempt}次重试...")
sleep(delay)
print("重试次数已用完,请求失败")
return None
这里有几个关键点:
- 超时设置:
timeout=10,防止请求卡死 - 状态码判断:429是限流,500是服务器内部错误,处理方式不同
- 指数退避:每次重试间隔可以递增,比如2秒、4秒、8秒
@retry就行了。代码复用性更好。
4.6 知识体系总览
下面这张图,是我自己总结的本章知识体系。你看一眼,心里就有数了:
4.7 完整实战案例
最后,我把今天讲的所有内容整合成一个完整的例子。这个函数可以获取某风场所有风机在指定时间段内的数据:
def get_wind_farm_data(farm_id, start_date, end_date, token):
base_url = f"https://api.windfarm.com/v1/farms/{farm_id}/data"
headers = {
"Authorization": f"Bearer {token}",
"Content-Type": "application/json"
}
all_records = []
page = 1
max_retries = 3
while True:
params = {
"start": start_date,
"end": end_date,
"page": page,
"page_size": 200
}
data = request_with_retry(base_url, headers, max_retries)
if data is None:
print("数据获取失败,终止")
break
records = data.get("records", [])
all_records.extend(records)
print(f"第{page}页:获取到{len(records)}条数据")
if len(records) < 200:
break
page += 1
print(f"共获取{len(all_records)}条数据")
return all_records
这个函数,说白了就是前面所有知识点的集合。你把它跑通了,API请求这块就算入门了。
- GET请求是API调用的基础,先跑通再说别的
- JSON解析用
response.json(),取值用data.get() - 分页数据要循环处理,注意总页数可能变化
- 错误处理和重试机制是生产环境的必备技能
好了,今天就到这里。代码不多,但都是干货。你回去把这段代码跑一遍,遇到问题随时来问我。