add by zhj: 我使用方法2“更新系统的certificate”解决了问题

原文:https://www.jianshu.com/p/8deb13738d2c

这两天在Linux上爬Google Play的app列表时,发现之前的脚本不能用了,总是报SSLError。花了一天的时间进行定位,虽然还是不明白为什么脚本之前能用,现在却不能用,但总算找到了解决办法。记录一下解决思路和过程,以供他人遇到类似问题时参考。

问题

脚本是用Python 3.4写的,用到了一个开源的库play-scraper,调用其collectionAPI来获取Google Play的Top App列表。该库使用了requests作为客户端来对Google Play进行操作。当脚本执行时,会报如下错误:certificate verify failed。

Traceback (most recent call last):
File "/home/me/py3.4/lib/python3.4/site-packages/urllib3/connectionpool.py", line 600, in urlopen
chunked=chunked)
File "/home/me/py3.4/lib/python3.4/site-packages/urllib3/connectionpool.py", line 345, in _make_request
self._validate_conn(conn)
File "/home/me/py3.4/lib/python3.4/site-packages/urllib3/connectionpool.py", line 844, in _validate_conn
conn.connect()
File "/home/me/py3.4/lib/python3.4/site-packages/urllib3/connection.py", line 326, in connect
ssl_context=context)
File "/home/me/py3.4/lib/python3.4/site-packages/urllib3/util/ssl_.py", line 325, in ssl_wrap_socket
return context.wrap_socket(sock, server_hostname=server_hostname)
File "/usr/local/lib/python3.4/ssl.py", line 365, in wrap_socket
_context=self)
File "/home/me/py3.4/lib/python3.4/site-packages/gevent/_ssl3.py", line 232, in __init__
raise x
File "/home/me/py3.4/lib/python3.4/site-packages/gevent/_ssl3.py", line 228, in __init__
self.do_handshake()
File "/home/me/py3.4/lib/python3.4/site-packages/gevent/_ssl3.py", line 545, in do_handshake
self._sslobj.do_handshake()
ssl.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:600) During handling of the above exception, another exception occurred: Traceback (most recent call last):
File "/home/me/py3.4/lib/python3.4/site-packages/requests/adapters.py", line 440, in send
timeout=timeout
File "/home/me/py3.4/lib/python3.4/site-packages/urllib3/connectionpool.py", line 630, in urlopen
raise SSLError(e)
urllib3.exceptions.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:600)

定位过程

仔细分析Traceback,发现问题出在def send(self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None)中。注意verify参数,默认为True。在play-scraper中也是将其设为True的,说明在SSL握手过程中要验证certificate的。

Google了一下错误信息,大致有以下几种解决方法:

1. 将verify设为False,不验证certificate

参考:https://stackoverflow.com/a/30373147/2510797
简单粗暴,但是有效。不报错误了,但总是有Insecure request的告警。对于有代码洁癖的本人来说,这显然是不能接受的,除非时间非常紧迫。继续定位。

2. 更新系统的certificate。

参考:https://stackoverflow.com/a/24212501/2510797

sudo apt-get install ca-certificates

看了一下所用Linux系统的ca-certificates package,确实比较老了,但之前一直没有问题。死马当活马医试试吧,但问题依旧。

3. 指定系统certificate的路径

参考: https://stackoverflow.com/a/16085737/2510797
Linux系统certificate的certificate路径在/etc/ssl/certs。使用verify="/etc/ssl/certs"试试,发现确实不报错误了。但是这个方法的弊端也是显而易见:play-scraper并没有在API中提供传入参数verify,必须要修改其代码才行。不同的操作系统,其certificate存放的位置肯定不一样,要是代码支持跨平台,就需要判断操作系统的类型,然后传入相应的verify值。对于一个相对使用比较广泛的requests库来说,这么做显然不太合理。

4. 使用certifi的certitificate路径

参考:https://stackoverflow.com/a/35791445/2510797
看了一下requests的文档,发现它使用了certifi package。然后再去看certifi的文档,发现其certificate路径有两个:certifi.where()certifi.old_where()。快速浏览了一下requests的源码,发现如果verify=True的话,所用的certificate就是certifi.where(),所以就试了一下old_where(),居然不报错了。但看到certifi的文档中建议尽量不要用old_where(),所以还是不甘心,继续定位。

5. 安装requests的security extras

参考:https://stackoverflow.com/a/39580231/2510797

pip install -U requests[security]

注意后面的方括号,pip会安装三个security相关的package:pyopenssl cryptography idna。
试了一下,果然有效,不再报错。再去读requests和urllib3的源码,发现确实使用了pyopenssl。具体是怎么用的,还没有来得及分析。
至此个人觉得比较好的解决方法基本成型:修改play-scraper的dependency,使用requests[security]来安装那三个安全相关的包。
另外,系统的openssl版本太旧或太新也可能会造成问题。在目前最新版本的openssl上,该解决方法是有效的。

总结

使用开源软件的好处是可以看实现源码,花点时间读源码,调试定位,问题基本不难解决。但是文档有可能不是那么完备,需要进行Google或仔细读源码。希望自己的分析思路对别人有所帮助吧。

作者:PythonDeveloper
链接:https://www.jianshu.com/p/8deb13738d2c
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

如何解决Requests的SSLError(转)的更多相关文章

  1. 解决python爬虫requests.exceptions.SSLError: HTTPSConnectionPool(host='XXX', port=443)问题

    爬虫时报错如下: requests.exceptions.SSLError: HTTPSConnectionPool(host='某某某网站', port=443): Max retries exce ...

  2. 关于requests.exceptions.SSLError: HTTPSConnectionPool

    问题: requests.exceptions.SSLError: HTTPSConnectionPool(host='mall.christine.com.cn', port=443): Max r ...

  3. python使用requests时报错requests.exceptions.SSLError: HTTPSConnectionPool

    报错信息 Traceback (most recent call last): File "<stdin>", line 1, in <module> Fi ...

  4. requests.exceptions.SSLError……Max retries exceeded with url错误求助!!!

    import requests head = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) Appl ...

  5. requests.exceptions.SSLError报错

    requests.exceptions.SSLError: HTTPSConnectionPool(host='www.baidu.com', port=443): Max retries excee ...

  6. pycharm fiddler requests.exceptions.SSLError

    一.SSL问题1.不启用fiddler,直接发https请求,不会有SSL问题(也就是说不想看到SSL问题,关掉fiddler就行) 2.启动fiddler抓包,会出现这个错误:requests.ex ...

  7. Python中request的post请求报requests.exceptions.SSLError:

    今天发送一个post请求,提示错误 requests.exceptions.SSLError: HTTPSConnectionPool(host='user.zaful.com', port=443) ...

  8. 解决requests获取源代码时中文乱码问题

    用requests获取源代码时,如果是中文网页,就可能会出现乱码,下面我以中关村的网站为例: import requests url = 'http://desk.zol.com.cn/meinv/' ...

  9. [未解决]报错:SSLError

    参考网友解决的方法 任何报SSLError类的错,解决方法: 引入ssl模块 import ssl 在url链接代码上方添加语句: ssl._create_default_https_context ...

随机推荐

  1. AI:WEB:1 Walkthrough

    AI: Web: 1 Vulnhub Walkthrough靶机下载:https://www.vulnhub.com/entry/ai-web-1,353/测试方法:    Nmap网络扫描    浏 ...

  2. 【数据库】数据库入门(四): SQL查询 - SELETE的进阶使用

    集合操作常用的集合操作主要有三种:UNION(联合集).INTERSECT(交叉集).EXCEPT(求差集).以上三种集合的操作都是直接作用在两个或者多个 SQL 查询语句之间,将所有的元组按照特定的 ...

  3. Oracle 11.2.0.4打补丁

    所需补丁及高版本opatch 上传后将p6880880_112000_Linux-x86-64.zip解压覆盖$ORACLE_HOME/OPatch目录即可 [oracle@localhost OPa ...

  4. github操作

    Github使用 1. 注册 ​ 官网:https://github.com/ 搜索项目 以压缩包的的形式下载demo 克隆项目 创建仓库 克隆项目,编写,完成上传,使用https请求,需要输入用户名 ...

  5. HTTP中分块编码(Transfer-Encoding: chunked)

    转自: 妙音天女--分块传输编码~ 参考链接: HTTP MDN--HTTP协议 一.背景: 持续连接的问题:对于非持续连接,浏览器可以通过连接是否关闭来界定请求或响应实体的边界:而对于持续连接,这种 ...

  6. 移动端好用的下拉加载上拉刷新插件 dropload插件

    入了很多下拉加载上拉刷新的插件,但是感觉都不好用,知道最近遇到这款dropload的插件,瞬间打开新世界的大门啊,无卡顿简单易用可配置 <!doctype html> <html&g ...

  7. nginx 常用的中间件

    1.--with-http_stub_status_module nginx客户端状态 # 打开default.conf文件 vim /etc/nginx/conf.d/default.conf # ...

  8. python递归和内置方法

    递归:函数调用自身 核心:递进的时候能够达到一个结果,问题规模越来越小(不一定要真正的达到):设置一个条件,能够让最后一次函数调用结束 练习: ​ 第一个人的姓名是16岁,后面每个人的年龄都比前一个大 ...

  9. zzulioj - 2623: 小H的作业题

    题目链接:http://acm.zzuli.edu.cn/problem.php?id=2623 题目描述        期末考试即将来临,同学们都积极的在图书馆复习.今天小H也来到图书馆复习,小H掏 ...

  10. restQL 微服务查询语言

    restQL 是一个强大的微服务查询语言,类似sql,支持并行.链式.过滤.同时官方也提供了多种语言的实现 而且还有一个manger 与 graphql 以及Falcor的比较 以下是来自官方的比较说 ...