Python中用requests模块抓取资料,可以出现我想要的资料,但是资料并不完整,后面会出现ConnectionError,可以怎么解决?我已经设置了Timeout。
我的代码如下:
from pprint import pprint
import requests
import json
dict_num = dict()
for num in range(1,1771):
url_api = "http://api.jisuapi.com/bencao/detail?appkey=bdc8ee0bb0227112&detailid={n}&isdetailed={n}".format(n=num)
r = requests.get (url_api,timeout=60)
data = r.json()
pprint (data)
detail2 = data
pprint (detail2)
with open ("bencao_detail2", mode="w", encoding="utf8") as file:
json.dump(detail2, file)
说明
其实这是爬虫的常见状况之一,即我们所要爬取的链接集合不可能都在第一次请求就成功爬取。
这里面的情况很多,比如网络不稳定,网站部署的策略(流量、反爬虫...)以及网站服务的拥塞情况等等。对于这种情况的解决我所知道的一般有如下几种常见方案:
等待重试
可以设置等待时间重试或者用队列将失败的请求放置到队列尾部,这种可以解决类似网络不稳定以及网站服务拥塞的情况。
设置代理池
在代理池中抽取(可用)代理,然后分配给每一个请求。这种可以(一定程度上)解决网站部署的一些策略,当然有些比较强的反爬虫策略不一定起作用的,这里就不展开了。当然,这个一般结合方案1来使用,因为还是会出现网络不稳定以及网站服务拥塞的情况嘛。
上面所述的方案是建立在你的爬虫逻辑/策略是没有问题的。如果你的Error是
404
(找不到文件或目录)或者500
(内部服务器错误)这种情况,显然你得修改你的爬取逻辑/策略了。所以这个地方是有必要获取HTTP状态码的。不过你这种爬取api的情况错误信息是会体现在返回json里面的。鉴于你的情况我的建议是方案1:等待重试
解决
首先说一个误区,你将
timeout
设成60s意义不大。设成60s几乎不能解决任何一种情况,而且也不需要这么高。timeout
大部分使用场景反而是不希望链接保持太长而迟迟没有结果,这种timeout
值也不会那么高。加上你每次请求的数据量不大,不如设低一点让他超时重试。再具体到你的代码:
我的方案,供参考
这里再说明一下,我这里用的是队列的方法,构建了很简单一个队列。
也可以用等待的方式
time.sleep(x)
,但我觉得没必要,不如直接处理下一个任务。失败的任务放到队列尾部,最后再试。
我初步试了一下,好像没啥问题。
如果你的程序中断了,记下到了哪一步,然后更改队列起始。