这两个exception纠结了好几天 ,都没有什么头绪。网上几乎没有搜索到任何有用的资料。第一个exception: socket.timeout,第二个exception: urllib3.exceptions.ReadTimeoutError。第一个明显是socket超时,第二个是urllib3里面的request read操作超时。第一次检查socket和request相关操作没发现特别问题。并且笔者另一个类似的python + selenium实例没有类似的任何问题。可以说这两个爬虫项目是底层设置是一致的,因为问题项目的出问题的那部分设置是从另一个没有问题的项目拷贝过来的。那问题究竟出在哪里?
按流程,执行该项目一次,没有发现问题,接着直接执行第二次,该exception就出现了。重复几次结果一致。
尝试关闭且重启webdriver问题依旧。webdriver启动和浏览网页是没有问题的,那么问题可能出现在下载部分。如图所示,socket.timeout 和 urlib3.exceptions.ReadTimeoutError明显和下载模块相关联。而另一个类似项目却没有这样的情况。那么极有可能是相同的设置,对于不同的网络状况产生不一样的结果。
仔细查看相关代码:
# Download module
...
ssl._create_default_https_context=ssl._create_default_https_context=ssl._create_unverified_context
socket.setdefaulttimeout(3)
...
response=requests.get(url, headers=headers, timeout=1)
# Selenium webdriver wait module
wait=WebDriverWait(self.driver, 5)
下载模块中,socket的timeout设置为3秒,requests的request请求timeout为1秒,而webdriver的wait timeout为5秒。这样一旦遇上延迟较大的网络线路而发生timeout exception时,按照上面的设置,第一个timeout就是requests,然后是socket,最后是webdriver的wait。显而易见,这样的设置在此种情况下是不妥当的。如果没有一定的基础知识和相当的经验很难发现问题。这三者表面属于不同层次和库模块,之间的关系其实是一致的。
我们知道不同网站所处的网络环境是不尽相同的。互联网的网络状况"参差不齐"。为了使爬虫任务能够适应复杂的互联网环境,项目的设置应该尽可能地考虑所有可能出现的状况,分析解决问题。
找到症结所在,问题自然迎刃而解。
# Download module
...
ssl._create_default_https_context=ssl._create_default_https_context=ssl._create_unverified_context
socket.setdefaulttimeout(10)
...
response=requests.get(url, headers=headers, timeout=10)
# Selenium webdriver wait module
wait=WebDriverWait(self.driver, 10)
当然,舍弃webdriver的wait或socket.setdefaulttimeout(),采取其它折中的方案也是可能的解决办法。