- 核心概念:什么是 API 和 JSON?
- Python 标准库方案:使用
requests库(强烈推荐)。 - 实战示例:一个完整的 GET 和 POST 请求流程。
- 处理常见问题:错误处理、认证、参数传递等。
- 进阶主题:异步请求、会话管理等。
核心概念
什么是 API?
API (Application Programming Interface),应用程序编程接口,你可以把它想象成一家餐厅的“服务员”:
- 你(客户端):想吃菜(请求数据)。
- 厨房(服务器):负责做菜(处理业务逻辑)。
- 服务员(API):你把菜单(API文档)告诉服务员,他把你点的菜(请求)告诉厨房,然后把做好的菜(响应)端给你。
在 Web 世界中,API 通常是一个 URL(网址),你通过 HTTP 请求(GET, POST, PUT, DELETE 等)来访问它,并获取数据。
什么是 JSON?
JSON (JavaScript Object Notation),是一种轻量级的数据交换格式,它易于人阅读和编写,也易于机器解析和生成,它是 API 之间传递数据最常用的格式。
一个 JSON 对象看起来很像 Python 的字典:
{
"name": "John Doe",
"age": 30,
"isStudent": false,
"courses": [
{"title": "History", "credits": 3},
{"title": "Math", "credits": 4}
]
}
Python 中有内置的 json 模块可以轻松地在 Python 字典/列表和 JSON 字符串之间进行转换。
Python 标准库方案:使用 requests
虽然 Python 内置了 urllib 库可以处理 HTTP 请求,但它非常繁琐,社区开发的 requests 库 是事实上的标准,它极大地简化了 HTTP 请求的发送。
第一步:安装 requests 库
如果你还没有安装,请在终端或命令行中运行:
pip install requests
实战示例
我们将以一个公开的测试 API JSONPlaceholder 为例,它是一个免费的在线 REST API,非常适合测试和学习。
示例 1:GET 请求(获取数据)
GET 请求通常用于从服务器获取数据,比如获取一个用户的信息。
import requests
import json # 用于美化输出
# API 端点,获取 ID 为 1 的用户
url = "https://jsonplaceholder.typicode.com/users/1"
try:
# 1. 发送 GET 请求
# get() 方法会自动处理 URL 编码等
response = requests.get(url)
# 2. 检查请求是否成功
# response.ok 会检查状态码是否在 200-399 范围内
# response.raise_for_status() 会在状态码为 4xx 或 5xx 时抛出异常
response.raise_for_status()
# 3. 解析 JSON 响应
# response.json() 会将响应内容(必须是有效的 JSON)解析为 Python 字典
user_data = response.json()
# 4. 使用数据
print(f"用户名: {user_data['name']}")
print(f"邮箱: {user_data['email']}")
print(f"公司: {user_data['company']['name']}")
# 打印整个字典,使用 json.dumps 美化格式
print("\n完整的用户数据:")
print(json.dumps(user_data, indent=4, ensure_ascii=False))
except requests.exceptions.HTTPError as http_err:
print(f"HTTP 错误发生: {http_err}")
except requests.exceptions.ConnectionError as conn_err:
print(f"连接错误发生: {conn_err}")
except requests.exceptions.Timeout as timeout_err:
print(f"请求超时: {timeout_err}")
except requests.exceptions.RequestException as err:
print(f"发生未知错误: {err}")
代码解析:
requests.get(url): 向指定的 URL 发送一个 GET 请求。response.raise_for_status(): 这是一个非常好的习惯,如果服务器返回了 4xx (客户端错误) 或 5xx (服务器错误) 的状态码,它会抛出一个HTTPError异常。response.json(): 这是requests库的魔力所在,它会自动解码响应内容,并将其解析为 Python 的字典或列表,如果响应不是有效的 JSON,它会抛出JSONDecodeError。try...except: 块用于捕获网络请求中可能发生的各种异常,如连接失败、超时等,使程序更健壮。
示例 2:POST 请求(发送/创建数据)
POST 请求通常用于向服务器发送数据,比如创建一个新的资源。
import requests
import json
# API 端点,用于创建新的帖子
url = "https://jsonplaceholder.typicode.com/posts"
# 准备要发送的数据(一个 Python 字典)
# requests 会自动将其转换为 JSON 格式
payload = {: "Python API 教程",
"body": "这是一个关于如何使用 Python 与 JSON API 交互的详细教程。",
"userId": 1
}
# 设置请求头,告诉服务器我们发送的是 JSON 数据
# 虽然 requests 会自动处理,但显式声明是更好的实践
headers = {
"Content-Type": "application/json"
}
try:
# 1. 发送 POST 请求
# json=payload 会自动将字典序列化为 JSON 字符串,并设置正确的 Content-Type 头
response = requests.post(url, json=payload, headers=headers)
# 2. 检查请求是否成功
response.raise_for_status()
# 3. 解析服务器返回的响应(通常是创建的新资源)
created_post = response.json()
print("成功创建新帖子!")
print(f"新帖子的 ID: {created_post['id']}")
print("服务器返回的完整数据:")
print(json.dumps(created_post, indent=4, ensure_ascii=False))
except requests.exceptions.HTTPError as http_err:
print(f"HTTP 错误发生: {http_err}")
except requests.exceptions.RequestException as err:
print(f"发生未知错误: {err}")
代码解析:
requests.post(url, json=payload, ...): 发送 POST 请求。json=payload: 这是requests提供的便捷功能,它会自动将 Python 字典payload序列化为 JSON 字符串,并自动在请求头中添加Content-Type: application/json,你也可以使用data=json.dumps(payload)来手动实现,但json=参数更简洁。headers: 我们手动指定了Content-Type,这是一种明确和规范的做法。
处理常见问题
查询参数 (Query Parameters)
当需要像 https://example.com/users?name=John&age=30 这样传递参数时,可以使用 params 参数。
url = "https://jsonplaceholder.typicode.com/users"
params = {
"username": "Bret" # 获取用户名为 'Bret' 的用户
}
response = requests.get(url, params=params)
users = response.json()
print(users) # 应该返回一个只包含一个用户的列表
认证 (Authentication)
许多 API 需要认证,常见的认证方式是 API Key,通常放在请求头中。
api_key = "YOUR_SECRET_API_KEY"
url = "https://api.example.com/data"
headers = {
"Authorization": f"Bearer {api_key}" # Bearer Token 是一种常见的认证方式
}
response = requests.get(url, headers=headers)
# ... 处理响应 ...
自定义请求头
除了 Content-Type 和 Authorization,你可能还需要设置其他头信息,User-Agent。
headers = {
"User-Agent": "MyApp/1.0 (myemail@example.com)",
"Accept": "application/json"
}
response = requests.get(url, headers=headers)
进阶主题
会话对象 (Session Object)
如果你需要向同一个主机发送多个请求,使用 Session 对象会更高效,它会保持一个连接池,复用 TCP 连接,并可以保存 cookies。
with requests.Session() as session:
# 会话级别的设置,比如认证头,会应用到所有后续请求
session.headers.update({"Authorization": "Bearer YOUR_TOKEN"})
# 第一个请求
response1 = session.get("https://jsonplaceholder.typicode.com/posts/1")
print("Post 1:", response1.json()['title'])
# 第二个请求,复用了会话和连接
response2 = session.get("https://jsonplaceholder.typicode.com/posts/2")
print("Post 2:", response2.json()['title'])
异步请求 (Asynchronous Requests)
对于需要同时发送大量请求的场景(例如爬取多个网页),异步可以大大提高效率。requests 库本身是同步的,但有一个优秀的异步版本叫做 httpx。
pip install httpx
import httpx
import asyncio
async def fetch_user(client, user_id):
response = await client.get(f"https://jsonplaceholder.typicode.com/users/{user_id}")
return response.json()
async def main():
# 使用 async with 创建一个异步客户端
async with httpx.AsyncClient() as client:
# 创建多个任务,并发执行
tasks = [fetch_user(client, i) for i in range(1, 6)]
users = await asyncio.gather(*tasks)
for user in users:
print(f"获取到用户: {user['name']}")
# 运行异步主函数
asyncio.run(main())
| 任务 | 推荐方法 | 说明 |
|---|---|---|
| 发送请求 | requests.get(), requests.post() |
核心方法,用于发送不同类型的 HTTP 请求。 |
| 传递数据 | json=payload (POST) |
自动将 Python 字典转为 JSON。 |
| 传递参数 | params=params_dict (GET) |
自动将字典转为 URL 查询字符串。 |
| 设置认证 | headers={'Authorization': '...'} |
在请求头中添加认证信息。 |
| 处理响应 | response.json() |
将 JSON 响应转为 Python 对象。 |
| 检查错误 | response.raise_for_status() |
简洁地处理 HTTP 错误。 |
| 高效请求 | requests.Session() |
为同一主机的多个请求保持连接和状态。 |
| 高性能请求 | httpx (异步) |
在需要高并发的场景下使用。 |
掌握 requests 库是 Python 开发者的必备技能,从简单的 GET/POST 请求开始,逐步学习处理各种复杂场景,你就能自如地与任何 REST API 进行交互了。
