🌈个人主页:https://blog.csdn.net/2401_86688088?type=blog
🔥 系列专栏:https://blog.csdn.net/2401_86688088/category_12797772.html
目录
(一)使用 requests.post() 发送 JSON 数据
(二)使用 requests.put() 发送 JSON 数据
前言
在现代的 Web 开发和网络编程中,HTTP 请求和数据交互已经成为必不可少的技术基础。Python 的 requests 模块因其简单易用、功能强大而广受欢迎,能够帮助开发者轻松发起各种网络请求并处理响应。然而,在实际应用中,开发者经常需要处理 SSL 证书验证、请求超时、自动重试以及会话管理等复杂的场景。此外,代理的使用可以帮助开发者绕过网络限制或匿名访问特定资源。本文详细介绍了如何使用 requests 模块处理这些问题,并通过 retrying 模块实现自动重试机制,帮助开发者应对网络不稳定性和临时故障的挑战。
一、SSL证书问题
SSL证书(Secure Sockets Layer Certificate)是一种数字证书,用于在客户端(通常是浏览器)和服务器之间建立安全的加密连接。SSL证书确保数据在传输过程中被加密,以防止未经授权的第三方窃听、篡改或伪造数据。SSL证书也可用于证明服务器的身份,使用户能够确认他们连接的是合法的网站。
使用 requests 模块进行 HTTP 请求时,可能会遇到涉及 SSL 证书的问题。 requests 模块默认会验证 SSL 证书,以确保连接的安全性。但是在某些情况下,例如访问自签名证书的服务器或开发环境中的测试服务器时,你可能需要跳过 SSL 证书验证或者指定自定义的证书。
(一)跳过 SSL 证书验证
如果你想跳过 SSL 证书的验证,可以使用 verify=False 参数。在某些测试场景中,这可能会非常有用。
示例:
import requests
url = 'https://example.com'
# 发起请求,并忽略 SSL 证书验证
response = requests.get(url, verify=False)
# 打印返回内容
print(response.text)
注意:跳过 SSL 验证可能会带来安全风险,仅在你明确知道需要跳过验证的情况下使用。同时,跳过 SSL 验证时,requests 模块会给出警告。你可以通过以下方式关闭这些警告:
import requests
from requests.packages.urllib3.exceptions import InsecureRequestWarning
# 禁用 SSL 警告
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
url = 'https://example.com'
response = requests.get(url, verify=False)
print(response.text)
(二)使用自定义的 SSL 证书
如果你有一个自签名证书或其他非标准的证书,可以使用 verify 参数指定证书的路径。
示例:
import requests
url = 'https://example.com'
# 指定证书的路径
response = requests.get(url, verify='/path/to/certfile.pem')
# 打印返回内容
print(response.text)
在这种情况下,requests 模块会使用你指定的证书来进行验证。
(三)使用客户端证书
有时服务器可能需要你提供客户端证书进行身份验证。这种情况下,你可以使用 cert 参数来指定你的证书和私钥文件。
示例:
import requests
url = 'https://example.com'
# 使用客户端证书,cert 参数可以是一个包含证书文件和密钥文件路径的元组
response = requests.get(url, cert=('/path/to/client_cert.pem', '/path/to/client_key.pem'))
# 打印返回内容
print(response.text)
(四)总结
-
跳过 SSL 验证:verify=False
-
指定自定义证书文件:verify='/path/to/certfile.pem'
-
使用客户端证书进行身份验证:cert=('/path/to/client_cert.pem', '/path/to/client_key.pem')
二、请求超时
使用 requests 模块进行网络请求时,可能会遇到网络延迟、服务器响应慢等问题,导致请求超时。为了避免请求长时间挂起,可以使用 timeout 参数来设置请求的超时时间。超时是指在指定时间内没有收到服务器的响应时,抛出超时异常。
(一)设置请求超时时间
requests 模块的 timeout 参数可以用来设置超时时间,单位是秒。可以指定一个总的超时时间,或者分别为连接时间和读取时间设置超时时间。
示例 1:设置总超时时间
import requests
url = 'https://example.com'
try:
# 设置超时时间为5秒
response = requests.get(url, timeout=5)
print(response.text)
except requests.exceptions.Timeout:
print("请求超时")
在这个例子中,如果在 5 秒内没有收到服务器的响应,程序会抛出 Timeout
异常。
示例 2:分别设置连接和读取的超时时间
你也可以分别为 连接 和 读取 设置不同的超时时间,传入一个元组 (connect_timeout, read_timeout)。
示例:
import requests
url = 'https://example.com'
try:
# 设置连接超时为3秒,读取超时为5秒
response = requests.get(url, timeout=(3, 5))
print(response.text)
except requests.exceptions.Timeout:
print("请求超时")
在这个例子中:
-
连接超时:客户端与服务器建立连接的时间限制(3秒)。
-
读取超时:客户端等待服务器发送数据的时间限制(5秒)。
(二)处理超时异常
当请求超时时,requests 会抛出 requests.exceptions.Timeout 异常。你可以使用 try 和 except 来捕获和处理这个异常,防止程序崩溃。
(三)设置合理的超时时间
-
短时间请求:如果你期望请求在很短的时间内完成(如API请求),可以设置较短的超时时间,以提高程序的响应性。
-
长时间请求:如果请求需要长时间处理(如下载大文件或与低速服务器通信),则需要设置一个较长的超时时间。
(四)总结
-
设置超时时间:使用 timeout 参数为请求设置合理的超时时间。
-
分别设置连接和读取超时时间:传入元组 (connect_timeout, read_timeout)。
-
处理超时异常:使用 try-except 块捕获和处理 requests.exceptions.Timeout 异常。
三、retrying模块的使用
retrying 模块用于实现自动重试操作,适用于处理临时失败的任务(如网络请求、文件读写等)。你可以通过配置重试次数、等待时间、异常捕获等来灵活控制重试的行为。以下是详细的使用介绍及示例。
(一)安装 retrying 模块
如果没有安装 retrying 模块,可以通过以下命令进行安装:
pip install retrying
(二)基本使用方法
可以使用 @retry 装饰器来包装需要重试的函数。当函数抛出异常时,retrying 会根据定义的策略自动重试。
示例:
from retrying import retry
@retry
def unreliable_function():
print("尝试执行...")
raise Exception("操作失败")
# 调用函数
unreliable_function()
在这个例子中,unreliable_function 会持续重试,因为它每次都会抛出异常。
(三)设置重试策略
1. 限制最大重试次数
可以使用 stop_max_attempt_number 参数限制重试的最大次数。
from retrying import retry
@retry(stop_max_attempt_number=3) # 最多重试3次
def unreliable_function():
print("尝试执行...")
raise Exception("操作失败")
unreliable_function()
这个例子中,函数最多会重试 3 次,如果仍然失败,最终会抛出异常。
2.设置固定等待时间
可以使用 wait_fixed 参数来设置每次重试之间的固定等待时间,单位是毫秒。
from retrying import retry
@retry(wait_fixed=2000) # 每次重试等待2秒
def unreliable_function():
print("尝试执行...")
raise Exception("操作失败")
unreliable_function()
在这个例子中,每次重试之间会等待 2 秒。
3.指数退避策略
retrying 还支持指数退避(exponential backoff)策略,重试的时间间隔会随着重试次数的增加而指数增长。
from retrying import retry
@retry(wait_exponential_multiplier=1000, wait_exponential_max=10000)
def unreliable_function():
print("尝试执行...")
raise Exception("操作失败")
unreliable_function()
在这个例子中,重试的时间间隔会从 1 秒开始,每次增长,直到最大等待时间为 10 秒。
4.根据特定异常类型重试
可以使用 retry_on_exception 参数指定特定的异常类型来触发重试。以下示例仅在捕获 IOError 时进行重试。
from retrying import retry
def retry_if_io_error(exception):
return isinstance(exception, IOError)
@retry(retry_on_exception=retry_if_io_error)
def unreliable_function():
print("尝试执行...")
raise IOError("发生了IO错误")
unreliable_function()
这个例子中,函数只会在抛出 IOError 时进行重试。
5.根据返回值进行重试
还可以通过 retry_on_result 参数指定函数返回特定结果时触发重试。例如,以下代码在函数返回 None 时重试。
from retrying import retry
@retry(retry_on_result=lambda result: result is None)
def unreliable_function():
print("尝试执行...")
return None # 如果返回 None,则触发重试
unreliable_function()
在这个例子中,函数每次返回 None
时会进行重试。
(四)组合多个参数
可以将多个参数组合使用来定制更复杂的重试策略。例如,限制重试次数、设置固定的等待时间,并指定特定的异常类型来进行重试。
from retrying import retry
@retry(stop_max_attempt_number=5, wait_fixed=2000, retry_on_exception=lambda e: isinstance(e, IOError))
def unreliable_function():
print("尝试执行...")
raise IOError("发生了IO错误")
unreliable_function()
在这个例子中,函数最多会重试 5 次,每次重试之间等待 2 秒,并且只在捕获 IOError 时触发重试。
(五)完整的异常处理
可以使用 try-except 语句捕获 retrying 的重试过程中的异常。
from retrying import retry
import requests
@retry(stop_max_attempt_number=3, wait_fixed=2000)
def unreliable_function():
print("尝试获取网页内容...")
response = requests.get("https://example.com")
return response
try:
unreliable_function()
except Exception as e:
print(f"最终失败:{e}")
在这个例子中,如果重试 3 次后仍然失败,except 块会捕获异常并输出错误信息。
(六)总结
retrying
模块为函数的自动重试提供了灵活的控制选项,包括:
-
最大重试次数 (
stop_max_attempt_number
) -
固定的重试等待时间 (
wait_fixed
) -
指数退避策略 (
wait_exponential_multiplier
和wait_exponential_max
) -
基于特定异常的重试 (
retry_on_exception
) -
基于函数返回值的重试 (
retry_on_result
)
四、发送json格式数据
使用 requests 模块发送 JSON 格式的数据非常简单。通过 requests.post() 或 requests.put() 方法,你可以将 Python 字典自动转换为 JSON 格式,并发送给服务器。requests 会在请求头中自动设置 Content-Type 为 application/json,你只需要通过 json 参数传入字典即可。
(一)使用 requests.post() 发送 JSON 数据
import requests
# 目标 URL
url = 'https://example.com/api/endpoint'
# 要发送的 JSON 数据
data = {
"name": "John Doe",
"age": 30,
"email": "johndoe@example.com"
}
# 发送 POST 请求,自动将字典转换为 JSON 格式
response = requests.post(url, json=data)
# 打印响应状态码和内容
print(response.status_code)
print(response.text)
在这个例子中:
-
url
是你要发送请求的目标服务器地址。 -
data
是要发送的 JSON 数据,格式是 Python 字典。 -
requests.post(url, json=data)
会自动将字典转换为 JSON,并发送到指定的url
。
(二)使用 requests.put() 发送 JSON 数据
同样,发送 PUT 请求时也可以使用相同的方法:
import requests
# 目标 URL
url = 'https://example.com/api/endpoint'
# 要发送的 JSON 数据
data = {
"name": "Jane Doe",
"age": 25,
"email": "janedoe@example.com"
}
# 发送 PUT 请求
response = requests.put(url, json=data)
# 打印响应状态码和内容
print(response.status_code)
print(response.text)
(三)手动设置请求头发送 JSON 数据
如果想手动设置请求头,也可以这样做:
import requests
import json
# 目标 URL
url = 'https://example.com/api/endpoint'
# 要发送的 JSON 数据
data = {
"name": "Alice",
"age": 28,
"email": "alice@example.com"
}
# 手动设置请求头,并将数据转换为 JSON 字符串
headers = {'Content-Type': 'application/json'}
response = requests.post(url, data=json.dumps(data), headers=headers)
# 打印响应状态码和内容
print(response.status_code)
print(response.text)
(四)总结
-
使用
requests.post()
或requests.put()
方法时,可以直接通过json
参数发送 JSON 数据,requests
会自动设置请求头和转换数据格式。 -
如果需要手动设置请求头,可以使用
headers
参数,并通过json.dumps()
将字典转换为 JSON 字符串。
五、session会话
requests.Session 是 Python 的 requests 库中一个非常有用的对象,用来保持会话状态。使用 Session 对象可以在多个请求中共享连接、Cookies、Headers 等信息。它的主要功能是为同一个服务器的多个请求创建一个持久的会话,从而减少重复连接的开销、维护登录状态等。
Session
的优势:
-
保持 Cookies:会话中可以保存并共享 Cookies,适合需要登录认证的场景。
-
减少连接开销:同一个会话可以复用底层的 TCP 连接,减少连接建立的耗时。
-
共享参数:可以在整个会话中共享请求头、认证信息、代理等。
(一)创建一个会话
使用 requests.Session() 创建会话对象。
示例:
import requests
# 创建会话
session = requests.Session()
# 通过会话发送请求
response = session.get('https://example.com')
# 打印响应内容
print(response.text)
# 关闭会话
session.close()
(二)保持 Cookies
当你使用会话发送请求时,Cookies 会在请求之间保持和共享,适合需要登录状态的操作。
示例:
import requests
# 创建一个会话对象
session = requests.Session()
# 登录的URL
login_url = 'https://example.com/login'
# 假设的登录表单数据
login_data = {
'username': 'user123',
'password': 'password'
}
# 登录
login_response = session.post(login_url, data=login_data)
print("登录后的Cookies:", session.cookies.get_dict())
# 登录后访问需要认证的页面
profile_url = 'https://example.com/profile'
profile_response = session.get(profile_url)
print("个人资料页面:", profile_response.text)
# 关闭会话
session.close()
在这个例子中,session 会在登录后保存并共享 Cookies,因此后续的请求不需要再次登录。
(三)共享 Headers 和其他配置
Session 可以设置默认的 Headers,这样所有使用会话的请求都会共享这些 Headers。
import requests
# 创建会话
session = requests.Session()
# 更新默认的请求头
session.headers.update({
'User-Agent': 'my-app/0.0.1',
'Accept': 'application/json'
})
# 使用会话发送请求
response = session.get('https://httpbin.org/get')
print(response.json())
# 关闭会话
session.close()
在这个示例中,所有通过 session 发出的请求都会使用 User-Agent 和 Accept 头信息。
(四)代理和身份验证
会话可以共享代理和身份验证信息,适合处理需要代理或身份验证的请求。
代理示例:
import requests
# 创建会话
session = requests.Session()
# 设置代理
session.proxies.update({
'http': 'http://10.10.1.10:3128',
'https': 'https://10.10.1.10:1080',
})
# 通过代理发送请求
response = session.get('https://httpbin.org/ip')
print(response.json())
# 关闭会话
session.close()
基本身份验证示例:
import requests
from requests.auth import HTTPBasicAuth
# 创建会话
session = requests.Session()
# 设置基本身份验证
session.auth = HTTPBasicAuth('user', 'password')
# 发送需要身份验证的请求
response = session.get('https://httpbin.org/basic-auth/user/password')
print(response.status_code)
# 关闭会话
session.close()
(五)关闭会话
使用完会话后,应该调用 session.close() 来释放资源。虽然 Python 的垃圾回收机制会自动处理未关闭的会话,但显式关闭会话是一种良好的实践。
(六)总结
-
Session 允许你在多次请求之间共享信息,例如 Cookies 和 Headers,适合处理登录认证、代理等需要保持会话状态的场景。
-
通过 requests.Session() 创建一个会话,使用 session.get() 或 session.post() 等方法发送请求,并在使用完毕后调用 session.close() 关闭会话。
-
会话有助于优化性能,减少重复的连接开销,使你的代码更高效。
六、代理
使用 Python 的 requests 模块时,代理(proxies)允许你通过中间服务器发送请求。这在绕过网络限制、匿名浏览或访问某些受限区域的网站时非常有用。你可以为 HTTP 和 HTTPS 请求设置不同的代理。
(一)设置代理
可以通过传递一个包含代理信息的字典给 proxies 参数来设置代理。代理字典的格式如下:
proxies = {
'http': 'http://proxy.server:port',
'https': 'https://proxy.server:port',
}
示例:使用 HTTP 和 HTTPS 代理
import requests
# 定义代理
proxies = {
'http': 'http://10.10.1.10:3128',
'https': 'https://10.10.1.10:1080',
}
# 发送请求并使用代理
response = requests.get('https://httpbin.org/ip', proxies=proxies)
# 打印响应内容
print(response.text)
在这个示例中,所有通过 requests.get() 发送的请求都会通过你指定的代理服务器路由。
(二)使用带认证的代理
有些代理服务器需要身份验证,你可以在代理 URL 中包含用户名和密码,格式如下:
proxies = {
'http': 'http://username:password@proxy.server:port',
'https': 'https://username:password@proxy.server:port',
}
示例:使用需要身份验证的代理
import requests
# 需要身份验证的代理
proxies = {
'http': 'http://user:pass@10.10.1.10:3128',
'https': 'https://user:pass@10.10.1.10:1080',
}
# 发送请求
response = requests.get('https://httpbin.org/ip', proxies=proxies)
# 打印响应
print(response.text)
在这种情况下,代理服务器会使用提供的用户名 user 和密码 pass 来进行身份验证。
(三)针对特定协议设置代理
可以只为 HTTP 或 HTTPS 请求单独设置代理,例如仅为 HTTP 设置代理:
proxies = {
'http': 'http://10.10.1.10:3128',
}
response = requests.get('http://httpbin.org/ip', proxies=proxies)
print(response.text)
(四)不通过代理访问特定 URL
如果你想为某些 URL 禁用代理(即使全局设置了代理),你可以通过 no_proxy 环境变量实现。
import os
# 设置不使用代理的 URL
os.environ["no_proxy"] = "example.com"
# 请求不使用代理的 URL
response = requests.get('http://example.com')
print(response.text)
(五)Session
中使用代理
如果你需要在整个会话中使用代理,可以在 requests.Session 对象中配置代理,这样所有通过该会话发送的请求都会使用代理。
示例:在会话中使用代理
import requests
# 创建会话对象
session = requests.Session()
# 为会话设置代理
session.proxies.update({
'http': 'http://10.10.1.10:3128',
'https': 'https://10.10.1.10:1080',
})
# 发送请求
response = session.get('https://httpbin.org/ip')
print(response.json())
# 关闭会话
session.close()
(六)使用 SOCKS 代理
如果你需要使用 SOCKS 代理,可以安装 requests[socks] 依赖,并设置代理格式为 socks5:// 或 socks5h://。你需要通过 pip 安装 requests 的 SOCKS 支持:
pip install requests[socks]
然后,你可以这样使用 SOCKS 代理:
import requests
# 设置 SOCKS 代理
proxies = {
'http': 'socks5://user:pass@10.10.1.10:1080',
'https': 'socks5://user:pass@10.10.1.10:1080',
}
# 发送请求
response = requests.get('https://httpbin.org/ip', proxies=proxies)
# 打印响应内容
print(response.text)
(七)总结
-
requests
模块支持通过 HTTP、HTTPS 以及 SOCKS 代理发送请求,可以使用proxies
参数来配置。 -
代理可以包括身份验证信息,如用户名和密码。
-
可以在全局范围或
Session
中使用代理,以提高效率。 -
对于需要特定代理或不使用代理的请求,可以灵活配置请求。
七、总结
通过本文的介绍,我们深入了解了如何使用 requests 模块处理 SSL 证书问题、设置请求超时、发送 JSON 格式数据以及使用代理服务器。同时,还介绍了如何通过 retrying 模块实现自动重试,处理临时性故障。此外,requests.Session 会话管理可以帮助开发者在多个请求中保持状态、共享 Cookies 和连接配置。代理的使用能够帮助开发者解决网络访问中的特殊需求。掌握这些技能,将极大提高你在网络编程中的效率和代码的健壮性,确保应用程序能够应对各种网络请求场景。