HTTP协议定义了多种请求方法,用于指定对资源执行的操作类型。Requests库支持所有常见的HTTP方法:
| 方法 | Requests函数 | 描述 |
|---|---|---|
| GET | requests.get() |
请求指定资源,用于获取数据 |
| POST | requests.post() |
向指定资源提交数据,用于创建新资源 |
| PUT | requests.put() |
替换指定资源的所有内容,用于更新资源 |
| PATCH | requests.patch() |
部分修改指定资源的内容 |
| DELETE | requests.delete() |
删除指定资源 |
| HEAD | requests.head() |
获取资源的元数据(响应头),不返回响应体 |
requests.options() |
获取服务器支持的HTTP方法 |
所有请求方法都返回一个Response对象,包含服务器返回的所有信息。
GET请求是最常见的HTTP请求方法,用于从服务器获取数据。
import requests
# 发送GET请求
response = requests.get('https://api.example.com/data')
# 检查请求是否成功
if response.status_code == 200:
# 获取响应内容
data = response.text
print(f"响应内容: {data}")
else:
print(f"请求失败,状态码: {response.status_code}")
response.status_code - HTTP状态码(200表示成功)response.text - 响应内容(字符串格式)response.content - 响应内容(字节格式)response.json() - 将JSON响应解析为Python对象response.headers - 响应头信息import requests
# 发送GET请求到测试API
url = "https://jsonplaceholder.typicode.com/posts/1"
response = requests.get(url)
# 输出响应信息
print(f"URL: {response.url}")
print(f"状态码: {response.status_code}")
print(f"响应头: {response.headers['content-type']}")
print(f"编码: {response.encoding}")
print(f"内容长度: {len(response.text)} 字符")
# 输出响应内容
print("\n响应内容:")
print(response.text)
import requests
from requests.exceptions import HTTPError, Timeout, RequestException
url = "https://jsonplaceholder.typicode.com/posts/1"
try:
# 设置超时时间为5秒
response = requests.get(url, timeout=5)
# 如果响应成功,没有抛出异常
response.raise_for_status()
except HTTPError as http_err:
print(f"HTTP错误发生: {http_err}")
except Timeout as timeout_err:
print(f"请求超时: {timeout_err}")
except RequestException as req_err:
print(f"请求异常: {req_err}")
except Exception as err:
print(f"其他错误: {err}")
else:
# 请求成功
print("请求成功!")
print(f"状态码: {response.status_code}")
print(f"响应内容前100字符: {response.text[:100]}...")
import requests
# 从API获取JSON数据
url = "https://jsonplaceholder.typicode.com/posts/1"
response = requests.get(url)
if response.status_code == 200:
# 解析JSON响应
data = response.json()
print("获取到的数据:")
print(f"用户ID: {data['userId']}")
print(f"文章ID: {data['id']}")
print(f"标题: {data['title']}")
print(f"内容: {data['body'][:50]}...") # 只显示前50个字符
# 也可以访问响应头信息
print(f"\n响应头信息:")
print(f"内容类型: {response.headers.get('content-type')}")
print(f"服务器: {response.headers.get('server')}")
print(f"日期: {response.headers.get('date')}")
else:
print(f"请求失败,状态码: {response.status_code}")
在GET请求中,经常需要向URL添加查询参数。Requests提供了两种方式来添加参数:
import requests
# 手动构建带参数的URL
base_url = "https://api.example.com/search"
params = "?q=python&page=2&limit=10"
url = base_url + params
response = requests.get(url)
import requests
# 使用params参数自动编码
url = "https://api.example.com/search"
params = {
"q": "python",
"page": 2,
"limit": 10
}
response = requests.get(url, params=params)
print(f"实际请求URL: {response.url}")
import requests
# 使用params传递多个参数
url = "https://httpbin.org/get"
params = {
"name": "张三",
"age": 25,
"skills": ["python", "javascript", "sql"],
"page": 1,
"per_page": 20
}
response = requests.get(url, params=params)
print(f"请求URL: {response.url}")
print(f"状态码: {response.status_code}")
# 查看服务器收到的参数
if response.status_code == 200:
data = response.json()
print("\n服务器收到的参数:")
print(data['args'])
{
"args": {
"age": "25",
"name": "张三",
"page": "1",
"per_page": "20",
"skills": ["python", "javascript", "sql"]
},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Host": "httpbin.org",
"User-Agent": "python-requests/2.28.1"
},
"origin": "123.45.67.89",
"url": "https://httpbin.org/get?name=张三&age=25&skills=python&skills=javascript&skills=sql&page=1&per_page=20"
}
params参数时,Requests会自动对参数进行URL编码skills=python&skills=javascript)POST请求用于向服务器提交数据,通常用于创建新资源或提交表单数据。
data参数,Content-Type为application/x-www-form-urlencodedjson参数,Content-Type为application/jsonfiles参数,Content-Type为multipart/form-dataimport requests
url = "https://httpbin.org/post"
# 表单数据
form_data = {
"username": "john_doe",
"password": "secret123",
"email": "john@example.com"
}
# 发送POST请求(表单数据)
response = requests.post(url, data=form_data)
print(f"状态码: {response.status_code}")
print(f"响应头Content-Type: {response.headers['content-type']}")
if response.status_code == 200:
result = response.json()
print("\n服务器收到的表单数据:")
print(result['form'])
import requests
import json
url = "https://httpbin.org/post"
# JSON数据
json_data = {
"title": "Python Requests教程",
"content": "这是关于Requests库的教程",
"author": {
"name": "张三",
"email": "zhangsan@example.com"
},
"tags": ["python", "http", "requests"],
"published": True
}
# 方法1:使用json参数(推荐)
response = requests.post(url, json=json_data)
print(f"状态码: {response.status_code}")
print(f"响应头Content-Type: {response.headers['content-type']}")
if response.status_code == 200:
result = response.json()
print("\n服务器收到的JSON数据:")
print(json.dumps(result['json'], indent=2, ensure_ascii=False))
# 方法2:手动序列化并设置请求头
headers = {'Content-Type': 'application/json'}
response = requests.post(url, data=json.dumps(json_data), headers=headers)
import requests
url = "https://httpbin.org/post"
# 准备文件
files = {
'file': ('example.txt', open('example.txt', 'rb'), 'text/plain'),
'image': ('photo.jpg', open('photo.jpg', 'rb'), 'image/jpeg')
}
# 其他表单字段
data = {
'description': '这是上传的文件',
'category': 'documents'
}
# 发送带文件的POST请求
response = requests.post(url, files=files, data=data)
print(f"状态码: {response.status_code}")
if response.status_code == 200:
result = response.json()
print("\n上传的文件信息:")
print(f"文件名: {result['files']['file']}")
print(f"图片名: {result['files']['image']}")
print(f"表单字段: {result['form']}")
json参数而不是手动序列化files参数,Requests会自动设置正确的Content-Typedata和files参数| 方法 | 示例代码 | 用途说明 |
|---|---|---|
| PUT |
|
替换整个资源,用于更新操作 |
| PATCH |
|
部分更新资源,只发送需要修改的字段 |
| DELETE |
|
删除指定资源 |
| HEAD |
|
获取资源元数据(响应头),不返回响应体 |
|
获取服务器支持的HTTP方法 |
import requests
base_url = "https://jsonplaceholder.typicode.com/posts"
print("=== 1. 获取所有文章 (GET) ===")
response = requests.get(base_url)
print(f"状态码: {response.status_code}, 文章数量: {len(response.json())}")
print("\n=== 2. 创建新文章 (POST) ===")
new_post = {
"title": "Python Requests教程",
"body": "这是关于Requests库的详细教程",
"userId": 1
}
response = requests.post(base_url, json=new_post)
print(f"状态码: {response.status_code}")
if response.status_code == 201: # 201表示资源创建成功
created_post = response.json()
post_id = created_post['id']
print(f"创建成功! 文章ID: {post_id}")
print("\n=== 3. 更新文章 (PUT) ===")
update_url = f"{base_url}/{post_id}"
updated_post = {
"id": post_id,
"title": "更新后的标题",
"body": "更新后的内容",
"userId": 1
}
response = requests.put(update_url, json=updated_post)
print(f"状态码: {response.status_code}")
if response.status_code == 200:
print("更新成功!")
print("\n=== 4. 部分更新文章 (PATCH) ===")
partial_update = {
"title": "再次更新的标题"
}
response = requests.patch(update_url, json=partial_update)
print(f"状态码: {response.status_code}")
if response.status_code == 200:
print("部分更新成功!")
print("\n=== 5. 删除文章 (DELETE) ===")
response = requests.delete(update_url)
print(f"状态码: {response.status_code}")
if response.status_code == 200:
print("删除成功!")
print("\n=== 6. 获取文章元数据 (HEAD) ===")
response = requests.head(f"{base_url}/1")
print(f"状态码: {response.status_code}")
print(f"响应头: {dict(response.headers)}")
print("\n=== 7. 查看支持的HTTP方法 (OPTIONS) ===")
response = requests.options(base_url)
print(f"状态码: {response.status_code}")
print(f"允许的HTTP方法: {response.headers.get('allow')}")
可以通过headers参数自定义请求头,这对于API认证、设置内容类型等场景非常重要。
import requests
url = "https://httpbin.org/headers"
# 自定义请求头
headers = {
'User-Agent': 'MyApp/1.0',
'Accept': 'application/json',
'Authorization': 'Bearer your-token-here',
'X-Custom-Header': 'CustomValue'
}
response = requests.get(url, headers=headers)
if response.status_code == 200:
data = response.json()
print("服务器接收到的请求头:")
print(data['headers'])
| 请求头 | 示例值 | 用途 |
|---|---|---|
User-Agent |
MyApp/1.0 |
标识客户端应用程序 |
Authorization |
Bearer token123 |
API认证令牌 |
Content-Type |
application/json |
请求体的媒体类型 |
Accept |
application/json |
客户端期望的响应类型 |
Accept-Language |
zh-CN,zh;q=0.9 |
客户端接受的语言 |
Referer |
https://example.com |
来源页面URL |
X-API-Key |
your-api-key |
API密钥(自定义头) |
为了防止请求无限制等待,应该总是设置超时时间。
import requests
from requests.exceptions import Timeout
url = "https://httpbin.org/delay/10" # 这个端点会延迟10秒响应
try:
# 设置超时时间为3秒
response = requests.get(url, timeout=3)
print("请求成功")
except Timeout:
print("请求超时!服务器在3秒内没有响应")
# 也可以分别设置连接超时和读取超时
try:
# 连接超时: 2秒, 读取超时: 5秒
response = requests.get(url, timeout=(2, 5))
print("请求成功")
except Timeout as e:
print(f"超时异常: {e}")
Session对象可以跨请求保持某些参数,如cookies、headers等,同时会自动使用连接池,提高性能。
import requests
# 创建Session对象
session = requests.Session()
# 为Session设置默认参数
session.headers.update({
'User-Agent': 'MyApp/1.0',
'Accept': 'application/json'
})
# 所有通过这个Session发送的请求都会使用这些默认参数
response1 = session.get('https://httpbin.org/get')
print(f"第一个请求状态码: {response1.status_code}")
# 可以临时覆盖默认参数
response2 = session.get('https://httpbin.org/get',
headers={'User-Agent': 'TempAgent'})
print(f"第二个请求状态码: {response2.status_code}")
# Session会自动处理cookies
response3 = session.post('https://httpbin.org/cookies/set/sessioncookie/123456789')
response4 = session.get('https://httpbin.org/cookies')
print(f"Cookies: {response4.json()}")
# 关闭Session(虽然不是必须的,但是好习惯)
session.close()
import requests
import time
def test_without_session():
"""不使用Session,每次创建新连接"""
start = time.time()
for i in range(10):
# 每次请求都创建新连接
response = requests.get('https://httpbin.org/get')
return time.time() - start
def test_with_session():
"""使用Session,重用连接"""
start = time.time()
with requests.Session() as session:
for i in range(10):
# 重用Session中的连接
response = session.get('https://httpbin.org/get')
return time.time() - start
# 运行测试
time_without_session = test_without_session()
time_with_session = test_with_session()
print(f"不使用Session: {time_without_session:.2f}秒")
print(f"使用Session: {time_with_session:.2f}秒")
print(f"性能提升: {(time_without_session - time_with_session)/time_without_session*100:.1f}%")
本章详细介绍了如何使用Requests库发送各种HTTP请求:
requests.get()获取数据,通过params参数传递查询参数requests.post()提交数据,支持表单、JSON和文件上传headers参数自定义请求头timeout参数防止请求无限等待在实际开发中,建议总是设置超时时间,对于需要发送多个请求到同一服务器的场景,使用Session对象可以提高性能。