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,恭喜你,通了。

小提示:我在项目中遇到过,有些API返回的状态码是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不可能一次性全给你,所以就有了分页。

常见的分页方式有两种:

分页方式 说明 示例参数
基于页码 通过pagepage_size控制 ?page=1&page_size=100
基于游标 通过cursoroffset控制 ?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

你看,逻辑其实很简单:先请求第一页,拿到总页数,然后一页一页往下翻,直到翻完。

避坑指南:我曾经遇到过一个问题,API返回的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 知识体系总览

下面这张图,是我自己总结的本章知识体系。你看一眼,心里就有数了:

API请求实战 发送GET请求 解析JSON响应 处理分页数据 设置URL和Headers 携带查询参数 response.json()方法 安全取值:data.get() 基于页码 vs 游标 循环翻页直到结束 错误处理与重试机制 超时与连接异常 指数退避重试

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()
  • 分页数据要循环处理,注意总页数可能变化
  • 错误处理和重试机制是生产环境的必备技能

好了,今天就到这里。代码不多,但都是干货。你回去把这段代码跑一遍,遇到问题随时来问我。

专注资料整理