可狱可囚的爬虫系列课程 16:爬虫重试机制

一、retrying模块简介

在爬虫中,因为我们是在线爬取内容,所以可能会因为网络、服务器等原因导致报错,那么这类错误出现以后,我们想要做的肯定是在报错处进行重试操作,Python提供了一个很好的模块,能够直接帮助我们实现重试操作,它就是retrying模块。当然,重试操作不仅仅只用于爬虫,还可以用于其他更广泛的领域。

retrying 是一个用Python编写的重试库,用于将重试行为添加到常规任务中,让你写的代码拥有重试功能。官方文档:https://github.com/rholder/retrying

二、案例讲解

我这里有一些网址,现在要求编写一个爬虫程序,将这些网站访问一遍,那么应该如何确保程序能够顺利的执行完成呢,有些小伙伴会说使用异常捕获防止程序出现意外,这是一种解决办法,那么如果我再要求一个网站的请求不能等待过长时间并且针对于有错误的地址进行重试,应该如何解决呢,这个时候我们就需要引入重试机制。

(1)无重试机制的爬虫

python 复制代码
import requests


def requests_url(href):
    URL = href
    Headers = {
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36'
    }
    resp = requests.get(url=URL, headers=Headers, timeout=3)
    if resp.status_code == 200:
        print(f'{href}访问成功')


UrlList = ['https://www.chinanews.com/scroll-news/news5.html', 'https://ssr4.scrape.center/',
           'https://www.chinanews.com/scroll-news/news12.html', 'https://www.chinanews.com/scroll-news/news3.html',
           'https://www.chinanews.com/scroll-news/news8.html', 'https://www.chinanews.com/scroll-news/news2.html',
           'https://www.chinanews.com/scroll-news/news11.html', 'https://www.chinanews.com/scroll-news/news1.html',
           'https://www.chinanews.com/scroll-news/news4.html', 'https://www.chinanews.com/scroll-news/news7.html',
           'https://www.chinanews.com/scroll-news/news10.html', 'https://www.chinanews.com/scroll-news/news9.html',
           'https://www.chinanews.com/scroll-news/news6.html']
for i in UrlList:
    print(f'正在访问:{i}')
    requests_url(i)

这段代码在执行时,报了Read timed out的异常提示超时,那么超时的原因有多种,可能是本地网络原因、也可能是网址服务器原因等,此时便需要使程序具备能够重试的功能。

(2)引入了重试机制的爬虫

接下来我们导入安装好的retrying模块,只要在需要重试的函数前面添加指定的装饰器,即可使程序具备重试功能,看以下修改:

python 复制代码
from retrying import retry


@retry
def requests_url(href):
    URL = href
    Headers = {
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36'
    }
    resp = requests.get(url=URL, headers=Headers, timeout=3)
    if resp.status_code == 200:
        print(f'{href}访问成功')

(3)重试机制修订

引入了 retrying 的代码存在一个弊端,如果这个网址本身就是联不通的,那么它会永远重试下去,这并不是我们想看到的,所以还要添加一下参数:stop_max_attempt_number(最大重试次数),可以给这个参数指定一个数字,比如下面指定的数字5,便是让其最多重试5次。

python 复制代码
from retrying import retry


@retry(stop_max_attempt_number=5)
def requests_url(href):
    URL = href
    Headers = {
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36'
    }
    resp = requests.get(url=URL, headers=Headers, timeout=3)
    if resp.status_code == 200:
        print(f'{href}访问成功')

但是这样的修改还是不尽人意,虽然添加了最大重试次数,但非常快速的机械性的连续重试,总有一种会随时出发反爬机制的感觉,所以还可以设置两次重试之间的等待时间:wait_fixed(单位是毫秒),代码如下:

python 复制代码
from retrying import retry


@retry(stop_max_attempt_number=5, wait_fixed=2000)
def requests_url(href):
    URL = href
    Headers = {
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36'
    }
    resp = requests.get(url=URL, headers=Headers, timeout=3)
    if resp.status_code == 200:
        print(f'{href}访问成功')

不过我还是建议重复性的操作添加点随机性比较好,将 wait_fixed 修改为 wait_random_min 和 wait_random_max,表示从指定的时间范围内随机一个等待时间。

python 复制代码
from retrying import retry


@retry(stop_max_attempt_number=5, wait_random_min=1000, wait_random_max=2000)
def requests_url(href):
    URL = href
    Headers = {
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36'
    }
    resp = requests.get(url=URL, headers=Headers, timeout=3)
    if resp.status_code == 200:
        print(f'{href}访问成功')

三、最终代码

python 复制代码
import requests
from retrying import retry

@retry(stop_max_attempt_number=5, wait_random_min=1000, wait_random_max=2000)
def requests_url(href):
    URL = href
    Headers = {
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36'
    }
    resp = requests.get(url=URL, headers=Headers, timeout=3)
    if resp.status_code == 200:
        print(f'{href}访问成功')

UrlList = ['https://www.chinanews.com/scroll-news/news5.html', 'https://ssr4.scrape.center/',
           'https://www.chinanews.com/scroll-news/news12.html', 'https://www.chinanews.com/scroll-news/news3.html',
           'https://www.chinanews.com/scroll-news/news8.html', 'https://www.chinanews.com/scroll-news/news2.html',
           'https://www.chinanews.com/scroll-news/news11.html', 'https://www.chinanews.com/scroll-news/news1.html',
           'https://www.chinanews.com/scroll-news/news4.html', 'https://www.chinanews.com/scroll-news/news7.html',
           'https://www.chinanews.com/scroll-news/news10.html', 'https://www.chinanews.com/scroll-news/news9.html',
           'https://www.chinanews.com/scroll-news/news6.html']
for i in UrlList:
    print(f'正在访问:{i}')
    try:
        requests_url(i)
    except:
        print('重试结束,依旧报错,跳过,进行下一项任务!')

四、总结

重试机制仅仅是让爬虫在某一网站访问不通的情况下多尝试几次,最终还是会报错,所以重试机制依旧需要与异常捕获结合使用。

相关推荐
Sinsa_SI3 分钟前
2024年12月中国电子学会青少年软件编程(Python)等级考试试卷(六级)答案 + 解析
python·等级考试·电子学会·真题·答案·六级
kfepiza22 分钟前
Python的循环和条件判断 笔记250303
开发语言·笔记·python
川石课堂软件测试1 小时前
涨薪技术|持续集成Git使用详解
开发语言·javascript·git·python·功能测试·ci/cd·单元测试
小小码农一只1 小时前
轻松部署 Stable Diffusion WebUI 并实现局域网共享访问:解决 Conda Python 版本不为 3.10.6 的难题
python·stable diffusion·conda
阿正的梦工坊1 小时前
解析 PyTorch 中的 torch.multinomial 函数
人工智能·pytorch·python
kcarly2 小时前
Web Snapshot 网页截图 模块代码详解
前端·python·网页截图
王有品2 小时前
python之爬虫入门实例
开发语言·爬虫·python
岱宗夫up2 小时前
【django初学者项目】
python·django·html
万山y2 小时前
curosr提示词推荐
python
麦麦大数据2 小时前
vue+neo4j 四大名著知识图谱问答系统
vue.js·人工智能·python·django·问答系统·知识图谱·neo4j