第 57 课:RESTful API 使用与数据解析
学习目标
完成本课学习后,你将能够:
- 理解 RESTful API 的基本概念和 HTTP 方法的含义。
- 使用
requests库向 API 发送 GET 和 POST 请求。 - 成功解析 API 返回的 JSON 格式数据。
- 掌握在请求中设置参数、请求头以及处理 API 响应状态码。
- 初步具备使用 Python 与网络服务进行数据交互的能力。
核心概念
1. RESTful API 是什么?
简单来说,API (Application Programming Interface) 是程序之间交流的"菜单"。而 RESTful API 是一种设计风格,它利用 HTTP 协议来实现客户端(比如我们的 Python 脚本)与服务器(提供数据或服务的网站)之间的通信。 你可以把它想象成去一家"数据餐厅"点餐:
- 资源 (Resource):菜单上的每道菜,对应 API 中的一个 URL(端点)。例如,
/users表示所有用户信息。 - 方法 (Method):你点菜的方式。
- GET:获取信息。相当于"我想看看菜单上有什么菜"。
- POST:提交/创建信息。相当于"我想新增一道菜"。
- PUT/PATCH:更新信息。相当于"我想修改这道菜的做法"。
- DELETE:删除信息。相当于"我想把这道菜从菜单上移除"。
2. JSON 数据格式
API 返回的数据大多是 JSON (JavaScript Object Notation) 格式。它非常像 Python 的字典和列表,非常易读。
{
"name": "Alice",
"age": 30,
"hobbies": ["coding", "reading", "hiking"]
}
对应的 Python 数据结构就是一个字典,其值可以是字符串、数字、列表,甚至另一个字典。
3. 状态码
服务器在响应请求时,会附带一个 HTTP 状态码,告诉我们请求是否成功。
- 2xx (成功):如
200 OK,201 Created。 - 4xx (客户端错误):如
400 Bad Request(请求有误),404 Not Found(资源不存在),401 Unauthorized(未授权)。 - 5xx (服务器错误):如
500 Internal Server Error(服务器内部错误)。
我们的代码应该根据状态码做出不同的处理。
代码示例
以下示例使用一个公开的测试 API jsonplaceholder 来演示如何进行 GET 和 POST 请求。
import requests
import json
# 1. 发送 GET 请求:获取用户列表
print("--- GET 请求示例 ---")
api_url = "https://jsonplaceholder.typicode.com/users"
response = requests.get(api_url)
# 检查请求是否成功 (状态码为 2xx)
if response.status_code == 200:
# 将响应的 JSON 内容解析为 Python 对象
users_data = response.json() # 这里直接得到一个 list
print(f"成功获取 {len(users_data)} 位用户的信息。")
# 打印第一个用户的姓名和邮箱
print(f"示例用户: {users_data[0]['name']}, 邮箱: {users_data[0]['email']}")
else:
print(f"请求失败,状态码: {response.status_code}")
# 可以尝试打印更多信息,比如错误文本
# print(response.text)
print("\n" + "="*50 + "\n")
# 2. 发送带查询参数的 GET 请求:获取特定用户的帖子
print("--- 带参数的 GET 请求示例 ---")
user_id = 1
params = {'userId': user_id}
posts_url = "https://jsonplaceholder.typicode.com/posts"
response = requests.get(posts_url, params=params)
if response.status_code == 200:
posts = response.json()
print(f"用户 {user_id} 共有 {len(posts)} 篇帖子。")
# 打印第一篇帖子的标题
print(f"第一篇帖子标题: {posts[0]['title']}")
else:
print(f"请求失败,状态码: {response.status_code}")
print("\n" + "="*50 + "\n")
# 3. 发送 POST 请求:模拟创建一篇新帖子
print("--- POST 请求示例 ---")
new_post = {
'title': '我的新帖子',
'body': '这是通过 Python 脚本自动创建的内容。',
'userId': 1
}
# 设置请求头,明确告知服务器我们发送的是 JSON 数据
headers = {'Content-Type': 'application/json'}
response = requests.post(
"https://jsonplaceholder.typicode.com/posts",
headers=headers,
json=new_post # 直接使用 `json` 参数,它会自动设置序列化和头部
)
# 对于 POST/PUT 请求,成功创建通常返回状态码 201
if response.status_code == 201:
created_post = response.json()
print(f"帖子创建成功!新帖子的ID为: {created_post['id']}")
print(f"返回的数据: {json.dumps(created_post, indent=2, ensure_ascii=False)}")
else:
print(f"创建失败,状态码: {response.status_code}")
print(f"错误详情: {response.text}")
实践练习
练习 1:基础数据获取
要求:使用 https://jsonplaceholder.typicode.com/todos 这个 API 端点,获取所有待办事项(todos)。
- 发送一个 GET 请求。
- 打印总共获取了多少条待办事项。
- 打印第一条待办事项的
title和completed字段的值。 预期输出示例:
成功获取 200 条待办事项。
第一条: "delectus aut autem", 完成状态: False
练习 2:查询参数过滤
要求:只获取"已完成"(completed 为 True)的待办事项。
- 查阅 API 文档或测试,了解如何用查询参数进行过滤(提示:在 URL 后加
?completed=true)。 - 使用
params字典实现。 - 打印符合条件的待办事项数量。 预期输出示例:
已完成的待办事项共有: 90 条。
练习 3:模拟数据提交与错误处理
要求:模拟向 /comments 端点发送一个无效的 POST 请求,并处理错误。
- 构造一个明显不符合 API 要求的请求体(例如,缺少必要字段)。
- 发送 POST 请求。
- 打印返回的状态码和响应文本。 预期输出示例:
请求失败,状态码: 400
错误详情: { ... } # API返回的错误JSON信息
常见错误
-
忘记检查状态码:直接调用
.json()。如果请求失败(如 404, 500),服务器可能返回的不是有效的 JSON(可能是 HTML 错误页面),这会导致JSONDecodeError。# 错误做法 data = response.json() # 如果 response 不是 200,可能在这里出错 # 正确做法 if response.status_code == 200: data = response.json() else: print(f"Error: {response.status_code}") # 处理错误情况 -
混淆
.json()和.text:.json()方法会自动将响应体解析为 Python 对象。如果你手动用json.loads(response.text),记得处理可能出现的解析异常。 -
POST/PUT 请求忘记设置
Content-Type:当发送 JSON 数据时,最好明确指定headers={'Content-Type': 'application/json'},或者更方便地,直接使用requests的json参数(它会自动设置)。 -
参数和数据混淆:
params用于 URL 查询参数(出现在?key=value后),data或json用于 请求体(POST/PUT 时发送的主要内容)。
小结
本课我们学习了与 RESTful API 交互的核心流程:
- 构建请求:确定目标 URL、HTTP 方法(GET/POST等)、参数(
params)和请求体(data/json)。 - 发送请求:使用
requests.get()、requests.post()等方法。 - 处理响应:首先检查状态码,然后使用
.json()方法解析成功的响应数据为 Python 字典或列表。 - 错误处理:对网络错误、无效 JSON、非 2xx 状态码等情况进行优雅处理,增强脚本的健壮性。
掌握这些技能,意味着你能够利用互联网上开放的 API 来获取实时数据、自动化在线服务,这是成为"全栈"或"数据"开发者的关键一步。在下一课,我们将结合 BeautifulSoup 库,学习如何从网页中提取结构化数据。