Python爬虫在进行多次请求的过程中,有时会出现请求超时的情况,这时我们可以使用重试机制来尝试多次请求。本文将介绍六种常见的Python爬虫重试方法。
第一种方法:使用requests库的timeout和retry参数
requests库本身提供了timeout和retry两个参数,我们可以使用它们来实现请求超时后的重试。
import requests
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.util.retry import Retry
# 创建重试策略
retry_strategy = Retry(
total=3,
backoff_factor=1,
status_forcelist=[500, 502, 503, 504]
)
# 创建session
session = requests.Session()
session.mount("http://", HTTPAdapter(max_retries=retry_strategy))
# 发送请求
try:
response = session.get('http://www.example.com', timeout=5)
print(response.status_code)
except Exception as e:
print(e)
该代码中,total表示重试次数,backoff_factor表示重试间隔时间的乘数因子,status_forcelist表示需要重试的HTTP状态码列表。我们使用Session对象来管理这个请求和它的重试。使用timeout设置请求超时时间,若请求超时,将会发生异常。
第二种方法:使用requests库和retrying库
retrying库可以在请求失败时实现自动重试,结合requests库可以方便地实现重试功能。
import requests
from retrying import retry
# 使用retrying装饰器
@retry
def get_response():
response = requests.get('http://www.example.com')
return response
# 调用函数
try:
response = get_response()
print(response.status_code)
except Exception as e:
print(e)
使用retrying库的retry装饰器来实现请求失败时的重试。默认情况下,retrying会在发生异常时重试3次。可以通过添加参数来自定义重试次数和重试间隔时间。
第三种方法:使用urllib库和time库
使用urllib库和time库可以实现简单的重试机制。
import urllib.error
import urllib.request
import time
# 发送请求
def get_response():
count = 0
while count < 3:
try:
response = urllib.request.urlopen('http://www.example.com', timeout=5)
return response.read()
except urllib.error.URLError as e:
if hasattr(e, 'code') and e.code >= 500 and e.code < 600:
print(f'Server error: {e.code}, Retry in 5 seconds...')
time.sleep(5)
count += 1
else:
raise e
raise Exception(f'Request Error after {count} times retry.')
# 调用函数
try:
response = get_response()
print(response)
except Exception as e:
print(e)
我们在get_response函数中使用while循环,判断请求次数是否小于3。若请求成功,返回response,否则判断异常类型是否是URLError,和状态码是否在500-599之间。若是,则等待5秒后重试,次数加1;否则,重新抛出异常。当请求次数达到3时,抛出异常。
第四种方法:使用timeout-decorator库
timeout-decorator库可以方便地为函数添加超时机制和重试机制。
from timeout_decorator import timeout, TimeoutError
from retrying import retry
# 使用timeout-decorator和retrying库
@timeout(5)
@retry(stop_max_attempt_number=3)
def get_response():
response = requests.get('http://www.example.com')
return response
# 调用函数
try:
response = get_response()
print(response.status_code)
except TimeoutError as t_error:
print(t_error)
except Exception as e:
print(e)
timeout-decorator库的timeout装饰器可以为函数添加超时机制,retrying库的retry装饰器可以为函数添加重试机制。由于timeout-decorator库自带超时机制,我们可以省略掉requests库中的timeout参数。stop_max_attempt_number表示最大重试次数。
第五种方法:使用tenacity库
Tenacity库是一个用于重试、回退和错误处理的Python库,可以方便地实现重试机制。
from tenacity import retry, stop_after_attempt, wait_fixed
# 使用tenacity库的retry装饰器
@retry(stop=stop_after_attempt(3), wait=wait_fixed(5))
def get_response():
response = requests.get('http://www.example.com')
return response
# 调用函数
try:
response = get_response()
print(response.status_code)
except Exception as e:
print(e)
使用tenacity库的retry装饰器来实现请求失败时的重试。使用stop_after_attempt函数设置最大重试次数,wait_fixed函数设置重试间隔时间。
第六种方法:使用backoff库
backoff库可以根据指数函数产生延迟时间,可以实现前几次请求间隔短,后面的请求间隔时间逐步增加的效果。
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.util.retry import Retry
import backoff
# 创建重试策略
retry_strategy = Retry(
total=3,
backoff_factor=1,
status_forcelist=[500, 502, 503, 504]
)
# 使用backoff库的on_predicate装饰器
@backoff.on_predicate(backoff.expo, max_tries=3)
def get_response():
session = requests.Session()
session.mount("http://", HTTPAdapter(max_retries=retry_strategy))
response = session.get('http://www.example.com')
return response
# 调用函数
try:
response = get_response()
print(response.status_code)
except Exception as e:
print(e)
在get_response函数中,我们使用on_predicate装饰器来设置函数执行失败时的重试策略。使用backoff.expo函数设置间隔时间的指数因子。max_tries表示最大重试次数。我们使用session对象来实现请求和重试,而不是使用requests库中的retry参数。