Python爬虫实例(三):错误重试,超时处理的解决方法

错误重试

错误重试用到的方法之一是:@retry()装饰器

装饰器实际是一个python函数,它的作用就是为被装饰的函数(或对象)进行装饰、包装,可以让被装饰的函数(或对象)在不需要做任何代码改动的情况下增加一些额外的功能,即被装饰函数(对象)的增强版。

安装 

pipenv install retrying

应用语法

from retrying import retry
# @retry((指定重试的错误类型), 参数设置),例如
@retry((ValueError, TypeError), stop_max_attempt_number=5)
def func_name():
    XXX

func_name()

常用的参数有:

1、stop_max_attempt_number:在停止之前尝试的最大次数,最后一次如果还是有异常则会抛出异常,停止运行,默认为5次

2、stop_max_delay:比如设置成10000,那么从被装饰的函数开始执行的时间点开始,到函数成功运行结束或者失败报错中止的时间点,只要这段时间超过10秒,则停止重试(单位是毫秒)

3、wait_fixed:设置在两次retrying之间的停留时间,单位毫秒

4、wait_random_minwait_random_max:用随机的方式产生两次retrying之间的停留时间。wait_random_min停留最短时间,默认为0,单位毫秒。wait_random_max停留最长时间,默认为1000,单位毫秒

6、retry_on_result:指定一个函数,如果指定的函数返回True,则重试;否则抛出异常退出(指定要在得到哪些结果的时候去retry,retry_on_result传入一个函数对象,在执行get_result成功后,会将函数的返回值通过形参result的形式传入retry_if_result_none函数中,如果返回值是None那么就进行retry,否则就结束并返回函数值)

def retry_if_result_none(result):
    return result is None

@retry(retry_on_result=retry_if_result_none)
def get_result():
    print 'Retry forever ignoring Exceptions with no wait if return value is None'
    return None

7、retry_on_exception: 指定一个函数,如果此函数返回指定异常,则会重试;如果不是指定的异常,则会退出

8、wait_exponential_multiplierwait_exponential_max:以指数的形式产生两次retrying之间的停留时间,产生的值为2^previous_attempt_number * wait_exponential_multiplier,  previous_attempt_number是前面已经retry的次数,如果产生的这个值超过了wait_exponential_max的大小,那么之后两个retrying之间的停留值都为wait_exponential_max


超时处理

爬虫可能会因为网络问题导致请求失败,或一直等待响应,这样会影响程序效率。为避免该问题,我们可以给requests的请求加上timeout参数,限制爬虫在一定的时间内需返回结果,否则就会报超时错误。

requests.get或requests.post——timeout参数的单位为,可以设置请求的超时时间,如果超出时间,则返回异常

response = requests.get(url, headers=headers, timeout=0.4)

自己编写超时函数装饰器

未完,待续。。。。


超时处理与retry装饰器的结合应用

爬虫请求中的timeout参数可以与retry装饰器结合使用。这样爬虫就可以避免偶然的网络波动导致的请求错误,会在设置的重试次数内重复发起请求。

import requests
from retrying import retry


# 全部报错才会报错,如果其中一次正常,则继续执行
# 两次retry之间等待2秒,重试5次
@retry(stop_max_attempt_number=5, wait_fixed=2000)
def get_request(url):
    response = requests.get(url, headers=headers, timeout=1)
    return response.content.decode()


headers = {"user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36"}
url = "https://www.baidu.com/"
print(get_request(url))

上面的例子,每次请求的超时限制是1秒,如果超过1秒未返回响应,则会报错。报错之后,会间隔2秒后再重新发起请求。只要其中一次正常,就会继续执行;否则,如果5次全部报错,才会报错。


捕捉异常

import requests
from retrying import retry


# 全部报错才会报错,如果其中一次正常,则继续执行
# 两次retry之间等待2秒,重试5次
@retry(stop_max_attempt_number=5, wait_fixed=1000)
def _get_request(url):
    response = requests.get(url, headers=headers, timeout=1)
    return response.content.decode()


def get_request(url):
    try:
        html_str = _get_request(url)
    except TimeoutError:  # 1
        html_str = 'TimeoutError'
    except:  # 2
        html_str = 'OtherError'
    return html_str


headers = {"user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36"}
url = "https://www.baidu.com/"
print(get_request(url))

上面# 2处的except下面会出现“too broad exception clauses”(This inspection highlights too broad exception clauses such as no exception class specified, or specified as 'Exception'.)这是由于# 2处的except没有指定具体的报错类型,所以会出现exception过于宽泛的提示。

参考:

python的retry模块

Python @retry装饰器的使用与实现案例(requests请求失败并重复请求)

                                                如果觉得内容不错,请扫码关注微信公众号,获取更多内容

                                        

  • 2
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

199铱

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值