这段时间在制作一个爬虫的时候发现了一个比较神奇的事情 python requests 包发起请求的时候设置 timeout 参数 竟然不起作用?
what 你要弄啥幺蛾子嘞, 后来各种找原因终于在别人的提醒下又看了下 requests 的文档才发现原来 timeout 设置超时只是指发起到对方服务器接受到请求这段时间,原文:timeout
仅对连接过程有效,与响应体的下载无关。 timeout
并不是整个下载响应的时间限制,而是如果服务器在 timeout
秒内没有应答,将会引发一个异常(更精确地说,是在timeout
秒内没有从基础套接字上接收到任何字节的数据时)If no timeout is specified explicitly, requests do not time out.
没办法,因为业务需要必须要严格控制响应时间只好利用 python 的多线程来制作了一个异步的限制函数执行时间的装饰器:
import requests,datetime,time
import threading
class MyThread(threading.Thread):
def __init__(self,target,args=()):
"""
why: 因为threading类没有返回值,因此在此处重新定义MyThread类,使线程拥有返回值
此方法来源 https://www.cnblogs.com/hujq1029/p/7219163.html?utm_source=itdadao&utm_medium=referral
"""
super(MyThread,self).__init__()
self.func = target
self.args = args
def run(self):
#接受返回值
self.result = self.func(*self.args)
def get_result(self):
#线程不结束,返回值为None
try:
return self.result
except Exception:
return None
#为了限制真实请求时间或函数执行时间的装饰器
def limit_decor(limit_time):
"""
:param limit_time: 设置最大允许执行时长,单位:秒
:return: 未超时返回被装饰函数返回值,超时则返回 None
"""
def functions(func):
#执行操作
def run(*params):
thre_func = MyThread(target=func,args=params)
#主线程结束(超出时长),则线程方法结束
thre_func.setDaemon(True)
thre_func.start()
#计算分段沉睡次数
sleep_num = int(limit_time // 1)
sleep_nums = round(limit_time % 1, 1)
#多次短暂沉睡并尝试获取返回值
for i in range(sleep_num):
time.sleep(1)
infor = thre_func.get_result()
if infor:
return infor
time.sleep(sleep_nums)
#最终返回值(不论线程是否已结束)
return thre_func.get_result()
return run
return functions
总之把这个装饰器对公司的部分代码进行了下优化, 效果是非常非常不错的。再也没有出现因单个爬虫请求超时而导致整个代码执行时间而延长的情况出现。
本文原创,如需转载请注明来源。
注 : 网络爬虫要尽量减小对被爬取网站影响, 如在被爬取网站每天访问量较小的时间段去爬取,一切为了和平发展。