【学习笔记0005】Python中 requests.get 超时与重试

  • Post author:
  • Post category:python


import requests

response = requests.get(url, timeout=(10, 15))
response.encoding ='utf-8'
html = response.text

timeout参数可以配置超时时间,一般情况我们只需要填一个数字,即可代表等待多少秒结束,但其实可以填一个元组的,要解释这个元组的作用,首先需要了解超时的两个概念:

A. 连接超时


连接超时是从客户端发起url请求,到与服务器建立起资源链接请求成功,中间所需要等待的最大时间

B. 读取超时


读取超时是客户端在与服务器已经建立资源链接请求成功后,开始获取资源并最后返回到客户端,中间所需要等待的最大时间

理解清楚以上两个概念后,我们回到参数 timeout 设置的元组 (10, 15),这里的连个数字分别代表 连接超时 和 读取超时,也就是说上诉代码在获取到url内容的结果之前,最多可能需要等待 10+15=25 秒,如果10秒之内(即连接超时时间内)还未成功获取资源则会触发

requests 包内置的重试机制,

关于这个机制,我后面再讲。

而通常情况下,我们设置超时时间只有一个数字,例如:

response = requests.get(url, timeout=10)
# response = requests.get(url, timeout=(10, 10))  # 效果等于上面代码

当只设置一个数字时,其实 requests 底层还是会当做两个数值即元组来处理,也就是说 requests 会将该数值

既作为连接超时又作为读取超时

去设置,那么最后在获取到url内容的结果之前,最多可能需要等待 10+10=20 秒,如果10秒之内(即连接超时时间内)还未成功则会触发重试机制。

最后讲一下我对 requests 重试机制的理解,众所周知攻城狮们不 FQ 的话,是肯定上不去 google 的,所以运行下面代码是肯定会报错且触发重试机制的:

import requests
from datetime import datetime

url = 'http://www.google.com'
print("开始......")
print(datetime.now())
response = requests.get(url)
response.encoding ='utf-8'
html = response.text
print(html)

输出情况如下:


结果分析:

可以看出上面出现了四次连接失败,requests 包在第一次去请求时,肯定是不知道是否能成功的,所以第一次不计入重试机制中的次数,那么重试机制的重试次数就是 4 – 1 = 3 次,当程序尝试3次后任然不成功,则返回。

思考:通常情况下,我们做爬虫经常会遇到被屏蔽的情况,而 requests 包自带的重试机制并不能满足实际需求,因为很少情况下是因为网络原因导致第一次请求不成功的,最有可能就是网站屏蔽了你的访问,那么重试机制里面的后面 3次请求就会显得没有意义,所以我们需要自己封装一个请求,让程序判断出请求异常时,就直接等待一段时间,然后再去重试请求。简单封装如下:

import requests, random, time

class Http():
     
    def get_html(self, url):
        try:
            return self.__request(url)
        except:            
            secends = random.randint(600, 1800)
            print('出现异常,休息一会儿......')
            print(str(secends) + '秒后继续')
            time.sleep(secends)   # 暂停10~30分钟,然后再尝试一次
            try:
                print('重试请求......')
                return self.__request(url)
            except:
                print('出现异常,休息一会儿......')
                print('30分钟后继续')
                time.sleep(1800)   # 暂停30分钟
                return ''

                
    def __request(self, url):
        response = requests.get(url, timeout=(10, 15)) 
        response.encoding ='utf-8'
        return response.text

如有不对的地方,希望提出!共勉!2019-12-25 15:17:24



版权声明:本文为adamlevine7原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。