Day 03 案例分析:requests 库与公开 API 调用

摘要要点

核心目标:掌握使用 Python requests 库调用 HTTP API 的基本技能,为后续调用 LLM API 打下基础。

三个核心案例

  1. 免费天气 API 调用(Open-Meteo)

    • 无需注册,适合初学者练习
    • 使用 requests.get()params 参数
    • 包含数据解析和格式化输出
  2. 需要 API Key 的接口调用

    • 模拟 LLM API 标准结构
    • 使用 headers 传递认证信息(Bearer Token)
    • 使用 json= 参数传递请求体
  3. 完整的错误处理机制

    • 处理超时(Timeout)、连接错误(ConnectionError)、HTTP 错误
    • 针对不同 HTTP 状态码(401、429、500 等)提供具体处理建议
    • 实现防御性编程

关键知识点

  • HTTP GET/POST 方法区别
  • JSON 数据格式处理
  • 状态码含义(200、404、500 等)
  • Query 参数和 Headers 的使用
  • raise_for_status() 简化错误检查
  • timeout 参数防止请求挂起

实践建议:将三个案例代码保存为 practice.py 并运行,通过 Open-Meteo API 立即获得实践反馈。

今日目标

掌握用 Python requests 库调用 HTTP API,为后续调用 LLM API 打基础。


核心概念速览

概念 通俗理解
HTTP GET 从服务器"取"数据,像打开网页
HTTP POST 向服务器"发"数据,像提交表单
JSON 数据格式,类似 Python 字典
状态码 200=成功,404=找不到,500=服务器出错
Headers 请求头,携带认证信息(API Key 就放这里)
Query 参数 URL 问号后的参数,如 ?city=Beijing

案例一:调用免费天气 API(Open-Meteo)

Open-Meteo 是免费无需注册的天气 API,非常适合练习。

完整代码

import requests
import json

def get_weather(latitude: float, longitude: float) -> dict:
    """调用 Open-Meteo API 获取当前天气"""
    url = "https://api.open-meteo.com/v1/forecast"
    
    params = {
        "latitude": latitude,
        "longitude": longitude,
        "current": "temperature_2m,wind_speed_10m,weather_code",
        "timezone": "Asia/Shanghai"
    }
    
    response = requests.get(url, params=params, timeout=10)
    response.raise_for_status()  # 状态码不是 2xx 就抛异常
    return response.json()


def describe_weather(data: dict) -> str:
    """把 API 返回的数据转成人类可读的描述"""
    current = data["current"]
    temp = current["temperature_2m"]
    wind = current["wind_speed_10m"]
    
    weather_codes = {
        0: "晴天", 1: "基本晴天", 2: "部分多云", 3: "阴天",
        45: "有雾", 51: "小毛毛雨", 61: "小雨", 63: "中雨", 65: "大雨",
        71: "小雪", 73: "中雪", 75: "大雪", 80: "阵雨", 95: "雷阵雨"
    }
    weather = weather_codes.get(current["weather_code"], "未知天气")
    
    return f"当前天气:{weather},气温 {temp}°C,风速 {wind} km/h"


if __name__ == "__main__":
    # 北京坐标
    data = get_weather(39.9042, 116.4074)
    print(describe_weather(data))
    
    # 打印完整 JSON 结构(帮助理解 API 返回格式)
    print("\n--- 原始 JSON ---")
    print(json.dumps(data["current"], indent=2, ensure_ascii=False))

执行流程拆解

1. 构造 URL + params → requests 自动拼成完整 URL
   https://api.open-meteo.com/v1/forecast?latitude=39.9042&longitude=116.4074&...

2. requests.get() 发送 HTTP 请求 → 服务器返回 Response 对象

3. response.raise_for_status() → 状态码检查(防御性编程)

4. response.json() → 把返回的 JSON 字符串解析成 Python dict

5. 从 dict 中提取需要的字段 → 组装成人类可读字符串

关键知识点

  • params={} 字典会被自动 URL 编码,不用手动拼字符串
  • timeout=10 防止请求永久挂起(真实项目必加)
  • raise_for_status() 是最简洁的错误检查方式

案例二:调用需要 API Key 的接口(模拟 LLM API 结构)

这个案例展示如何传递认证信息,结构和你以后调用 Claude/OpenAI API 完全一样。

import requests

def call_api_with_auth(api_key: str, prompt: str) -> str:
    """模拟调用需要认证的 API(结构与 LLM API 相同)"""
    
    url = "https://httpbin.org/post"  # httpbin 是一个回显请求内容的测试 API
    
    headers = {
        "Authorization": f"Bearer {api_key}",  # Bearer Token 认证(LLM API 标准格式)
        "Content-Type": "application/json"
    }
    
    body = {
        "model": "some-model",
        "messages": [
            {"role": "user", "content": prompt}
        ]
    }
    
    response = requests.post(url, headers=headers, json=body, timeout=10)
    response.raise_for_status()
    
    # httpbin 会把你发的请求原样返回,可以检查你发出的内容是否正确
    echo = response.json()
    print("服务器收到的 headers:", echo["headers"].get("Authorization"))
    print("服务器收到的 body:", echo["json"])
    
    return "调用成功"


if __name__ == "__main__":
    call_api_with_auth("my-secret-key-123", "你好!")

为什么这个案例重要?

后面调用 Claude API 时,代码结构一模一样

# 真实 Claude API 调用(Week 2 就会写这个)
response = requests.post(
    "https://api.anthropic.com/v1/messages",
    headers={
        "x-api-key": "your-key",
        "anthropic-version": "2023-06-01",
        "Content-Type": "application/json"
    },
    json={
        "model": "claude-opus-4-8",
        "max_tokens": 1024,
        "messages": [{"role": "user", "content": "Hello"}]
    }
)

今天学的 headers 传认证、json= 传请求体,这两个动作在调用 LLM API 时每天都要用。


案例三:错误处理全套(真实项目级别)

import requests
from requests.exceptions import Timeout, ConnectionError, HTTPError

def robust_api_call(url: str, params: dict) -> dict | None:
    """带完整错误处理的 API 调用"""
    try:
        response = requests.get(url, params=params, timeout=10)
        response.raise_for_status()
        return response.json()
    
    except Timeout:
        print("请求超时,请检查网络或稍后重试")
    except ConnectionError:
        print("网络连接失败,请检查网络设置")
    except HTTPError as e:
        status = e.response.status_code
        if status == 401:
            print("API Key 无效或过期")
        elif status == 429:
            print("请求频率超限(Rate Limit),请稍后重试")
        elif status == 500:
            print("服务器内部错误,不是你的问题")
        else:
            print(f"HTTP 错误:{status}")
    
    return None

三种错误的本质区别

错误类型 原因 处理策略
Timeout 服务器太慢或网络差 重试,加指数退避
ConnectionError 根本连不上服务器 检查网络/URL
HTTPError 连上了但服务器拒绝 看状态码决定

今日代码练习建议

把以上三个代码片段存成 practice.py,逐一运行,观察输出结果。
Open-Meteo 不需要注册,直接可以跑通案例一。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐