Requests - 使用 Requests
Requests - 发送 HTTP 请求
Section titled “Requests - 发送 HTTP 请求”Requests 库的主要目的是简化向 Web 服务器发送 HTTP 请求以及处理其响应的过程。本章介绍基础知识:发送基本的 GET 请求、传递 URL 参数以及检查响应的不同部分。
发送简单的 GET 请求
Section titled “发送简单的 GET 请求”GET 方法是最常见的 HTTP 方法,用于从指定的资源中检索数据。要发送 GET 请求,首先导入 requests 模块:
import requests然后,使用 requests.get() 函数,提供您要访问的资源的 URL。此函数返回一个 Response 对象,其中包含服务器对您的请求的响应。
import requests
# A common public API for examples# 一个常用的公共 API 作为示例url = 'https://jsonplaceholder.typicode.com/todos/1'
try: response = requests.get(url) # The 'response' object itself gives some info when printed # 'response' 对象本身在打印时提供一些信息 print(f'Response Object: {response}')except requests.exceptions.RequestException as e: print(f'Request failed: {e}') print(f'请求失败: {e}')Response Object: <Response [200]>响应对象: <Response [200]>输出 <Response [200]> 表示请求成功,服务器返回的 HTTP 状态码是 200 (OK)。
Response 对象包含关于服务器回复的丰富信息。主要的属性和方法包括:
- Status Code:
response.status_code(整数)提供 HTTP 状态码。response.ok布尔属性在status_code小于 400 时为True(即不是错误)。 - Headers:
response.headers是一个不区分大小写的类似字典的对象,包含响应头(例如,Content-Type、Date、Server)。 - Text Content:
response.text将响应体作为字符串返回。Requests 会尝试使用适当的编码对其进行解码(通常在头部中找到,或默认为 UTF-8)。您可以使用response.encoding检查或覆盖编码。 - Byte Content:
response.content将响应体作为原始字节返回。这适用于非文本内容,如图像、音频或其他二进制文件。 - JSON Content: 如果响应内容类型是 JSON(例如,
application/json),response.json()将其解析为 Python 字典或列表。如果内容不是有效的 JSON,它会引发requests.exceptions.JSONDecodeError。
处理潜在的错误至关重要。response.raise_for_status() 方法是一种便捷的方式,可以在请求导致不成功的状态码(4xx 客户端错误或 5xx 服务器错误)时引发 requests.exceptions.HTTPError。
import requests
url = 'https://jsonplaceholder.typicode.com/todos/1'
try: response = requests.get(url, timeout=5) # Added a timeout # 添加了超时设置 response.raise_for_status() # Check for HTTP errors (4xx or 5xx) # 检查 HTTP 错误(4xx 或 5xx)
print(f'Status Code: {response.status_code}') print(f'Is response OK? {response.ok}') print(f'Content-Type Header: {response.headers.get("Content-Type")}') print(f'状态码: {response.status_code}') print(f'响应是否成功 (OK)? {response.ok}') print(f'Content-Type 头部: {response.headers.get("Content-Type")}')
# Get JSON data since this API returns JSON # 获取 JSON 数据,因为此 API 返回 JSON todo_item = response.json() print('\nParsed JSON Data:') print('\n解析后的 JSON 数据:') print(todo_item) print(f"Item Title: {todo_item.get('title')}") print(f"项目标题: {todo_item.get('title')}")
# Example of accessing raw text (though json() is better for JSON data) # 访问原始文本的示例(尽管对于 JSON 数据来说 json() 更好) # print('\nRaw Text Data (first 100 chars):') # print('\n原始文本数据(前 100 个字符):') # print(response.text[:100] + '...' if len(response.text) > 100 else response.text)
except requests.exceptions.HTTPError as http_err: print(f'HTTP error occurred: {http_err} - Status Code: {http_err.response.status_code}') print(f'发生 HTTP 错误: {http_err} - 状态码: {http_err.response.status_code}')except requests.exceptions.JSONDecodeError as json_err: print(f'JSON decode error: {json_err}') print(f'JSON 解码错误: {json_err}')except requests.exceptions.RequestException as e: print(f'An error occurred: {e}') print(f'发生错误: {e}')Status Code: 200Is response OK? TrueContent-Type Header: application/json; charset=utf-8
Parsed JSON Data:{ 'userId': 1, 'id': 1, 'title': 'delectus aut autem', 'completed': False}Item Title: delectus aut autem状态码: 200响应是否成功 (OK)? TrueContent-Type 头部: application/json; charset=utf-8
解析后的 JSON 数据:{ 'userId': 1, 'id': 1, 'title': 'delectus aut autem', 'completed': False}项目标题: delectus aut autem传递 URL 参数(查询字符串)
Section titled “传递 URL 参数(查询字符串)”通常,您需要将数据作为 URL 查询字符串的一部分发送到服务器(例如,example.com/search?query=python&page=1)。Requests 通过允许您将参数字典传递给 requests.get() 方法的 params 参数来简化此操作。
import requests
# Using httpbin.org/get, which reflects the request's arguments# 使用 httpbin.org/get,它会反映请求的参数base_url = 'https://httpbin.org/get'
query_parameters = {'name': 'Alice', 'age': 30, 'city': 'Wonderland'}
try: response = requests.get(base_url, params=query_parameters, timeout=5) response.raise_for_status()
print(f'Constructed Request URL: {response.url}') print('\nServer saw these arguments (from response JSON):') print(f'构造的请求 URL: {response.url}') print('\n服务器看到的参数(来自响应 JSON):') # httpbin.org/get returns a JSON where 'args' contains the query parameters # httpbin.org/get 返回一个 JSON,其中 'args' 包含查询参数 print(response.json().get('args'))
except requests.exceptions.RequestException as e: print(f'An error occurred: {e}') print(f'发生错误: {e}')Constructed Request URL: https://httpbin.org/get?name=Alice&age=30&city=Wonderland
Server saw these arguments (from response JSON):{'name': 'Alice', 'age': '30', 'city': 'Wonderland'}(Note: Values in 'args' are strings as they are parsed from the URL)构造的请求 URL: https://httpbin.org/get?name=Alice&age=30&city=Wonderland
服务器看到的参数(来自响应 JSON):{'name': 'Alice', 'age': '30', 'city': 'Wonderland'}(注意:'args' 中的值是字符串,因为它们是从 URL 中解析的)Requests 会自动对参数进行 URL 编码并构建完整的查询字符串。
除了 GET:其他 HTTP 方法(例如 POST)
Section titled “除了 GET:其他 HTTP 方法(例如 POST)”Requests 完全支持其他 HTTP 方法,如 POST、PUT、DELETE、HEAD 和 OPTIONS。例如,POST 请求通常用于向服务器发送数据以创建或更新资源。
您可以在请求体中发送数据。对于表单编码的数据,使用 data 参数并传递字典。对于 JSON 数据,使用 json 参数更简单:
import requests
# httpbin.org/post reflects the POSTed data# httpbin.org/post 会反映 POST 的数据url_post = 'https://httpbin.org/post'
# Sending JSON data# 发送 JSON 数据json_payload = {'username': 'testuser', 'email': 'test@example.com', 'active': True}
try: response = requests.post(url_post, json=json_payload, timeout=5) response.raise_for_status()
print('JSON POST Response Details:') print('JSON POST 响应详情:') print(f'Status Code: {response.status_code}') print(f'状态码: {response.status_code}')
# httpbin.org/post returns a JSON that includes the parsed JSON payload under 'json' # httpbin.org/post 返回一个 JSON,其中包含解析后的 JSON 数据,位于 'json' 键下 returned_data = response.json() print(f'Sent JSON payload as received by server: {returned_data.get("json")}') print(f'Request Content-Type header: {returned_data.get("headers", {}).get("Content-Type")}') print(f'服务器接收到的发送的 JSON 数据: {returned_data.get("json")}') print(f'请求 Content-Type 头部: {returned_data.get("headers", {}).get("Content-Type")}')
except requests.exceptions.RequestException as e: print(f'An error occurred during POST: {e}') print(f'POST 过程中发生错误: {e}')JSON POST Response Details:Status Code: 200Sent JSON payload as received by server: {'username': 'testuser', 'email': 'test@example.com', 'active': True}Request Content-Type header: application/jsonJSON POST 响应详情:状态码: 200服务器接收到的发送的 JSON 数据: {'username': 'testuser', 'email': 'test@example.com', 'active': True}请求 Content-Type 头部: application/json当您使用 json 参数时,Requests 会自动将您的 Python 字典序列化为 JSON 字符串,并将 Content-Type 头部设置为 application/json。
网络操作有时会很慢或无限期地挂起。为了防止程序永远等待,始终为您的请求指定一个超时时间。Requests 中的 timeout 参数可以是单个浮点数(表示连接和读取超时时间的总和),也可以是一个元组 (connect_timeout, read_timeout)。
import requests
# httpbin.org/delay/N endpoint delays the response by N seconds# httpbin.org/delay/N 端点会将响应延迟 N 秒url_delayed = 'https://httpbin.org/delay/3'
try: # Timeout set to 2 seconds, which is less than the server's 3-second delay # 超时设置为 2 秒,少于服务器的 3 秒延迟 print('Attempting request with 2s timeout (expected to time out)...') print('尝试发送 2 秒超时请求(预期会超时)...') response = requests.get(url_delayed, timeout=2) print('Request successful (this should not be reached).') print('请求成功(不应该执行到这里)。')except requests.exceptions.Timeout: print('The request timed out as expected after 2 seconds.') print('请求在 2 秒后按预期超时。')except requests.exceptions.RequestException as e: print(f'An unexpected error occurred: {e}') print(f'发生意外错误: {e}')
try: # Timeout set to 5 seconds, which is more than the server's 3-second delay # 超时设置为 5 秒,多于服务器的 3 秒延迟 print('\nAttempting request with 5s timeout (expected to succeed)...') print('\n尝试发送 5 秒超时请求(预期会成功)...') response = requests.get(url_delayed, timeout=5) response.raise_for_status() print(f'Request successful within 5 seconds. Status: {response.status_code}') print(f'请求在 5 秒内成功。状态码: {response.status_code}')except requests.exceptions.Timeout: print('The request timed out (this should not happen with a 5s timeout for a 3s delay).') print('请求超时(对于 3 秒延迟,设置为 5 秒超时不应该发生)。')except requests.exceptions.RequestException as e: print(f'An error occurred: {e}') print(f'发生错误: {e}')Attempting request with 2s timeout (expected to time out)...The request timed out as expected after 2 seconds.
Attempting request with 5s timeout (expected to succeed)...Request successful within 5 seconds. Status: 200尝试发送 2 秒超时请求(预期会超时)...请求在 2 秒后按预期超时。
尝试发送 5 秒超时请求(预期会成功)...请求在 5 秒内成功。状态码: 200设置适当的超时时间是编写健壮的网络应用程序的最佳实践。