python爬虫ssl错误_Python爬虫:Requests的SSLError:certificate verify failed问题解决方案6条...
問(wèn)題:腳本是用Python寫(xiě)的,用到開(kāi)源庫(kù)play-scraper,調(diào)用其collectionAPI來(lái)獲取Google Play的Top App列表。該庫(kù)使用了requests作為客戶端來(lái)對(duì)Google Play進(jìn)行操作。當(dāng)腳本執(zhí)行時(shí),會(huì)報(bào)如下錯(cuò)誤:certificate verify failed。
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)
定位過(guò)程
仔細(xì)分析Traceback,發(fā)現(xiàn)問(wèn)題出在def send(self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None)中。注意verify參數(shù),默認(rèn)為T(mén)rue。在play-scraper中也是將其設(shè)為T(mén)rue的,說(shuō)明在SSL握手過(guò)程中要驗(yàn)證certificate的。
Google了一下錯(cuò)誤信息,大致有以下幾種解決方法:
1. 將verify設(shè)為False,不驗(yàn)證certificate
參考:https://stackoverflow.com/a/30373147/2510797
簡(jiǎn)單粗暴,但是有效。不報(bào)錯(cuò)誤了,但總是有Insecure request的告警。對(duì)于有代碼潔癖的本人來(lái)說(shuō),這顯然是不能接受的,除非時(shí)間非常緊迫。繼續(xù)定位。
2. 更新系統(tǒng)的certificate。
參考:https://stackoverflow.com/a/24212501/2510797
sudo apt-get install ca-certificates
看了一下所用Linux系統(tǒng)的ca-certificates package,確實(shí)比較老了,但之前一直沒(méi)有問(wèn)題。死馬當(dāng)活馬醫(yī)試試吧,但問(wèn)題依舊。
3. 指定系統(tǒng)certificate的路徑
參考: https://stackoverflow.com/a/16085737/2510797
Linux系統(tǒng)certificate的certificate路徑在/etc/ssl/certs。使用verify="/etc/ssl/certs"試試,發(fā)現(xiàn)確實(shí)不報(bào)錯(cuò)誤了。但是這個(gè)方法的弊端也是顯而易見(jiàn):play-scraper并沒(méi)有在API中提供傳入?yún)?shù)verify,必須要修改其代碼才行。不同的操作系統(tǒng),其certificate存放的位置肯定不一樣,要是代碼支持跨平臺(tái),就需要判斷操作系統(tǒng)的類(lèi)型,然后傳入相應(yīng)的verify值。對(duì)于一個(gè)相對(duì)使用比較廣泛的requests庫(kù)來(lái)說(shuō),這么做顯然不太合理。
4. 使用certifi的certitificate路徑
參考:https://stackoverflow.com/a/35791445/2510797
看了一下requests的文檔,發(fā)現(xiàn)它使用了certifi package。然后再去看certifi的文檔,發(fā)現(xiàn)其certificate路徑有兩個(gè):certifi.where()和certifi.old_where()。快速瀏覽了一下requests的源碼,發(fā)現(xiàn)如果verify=True的話,所用的certificate就是certifi.where(),所以就試了一下old_where(),居然不報(bào)錯(cuò)了。但看到certifi的文檔中建議盡量不要用old_where(),所以還是不甘心,繼續(xù)定位。
5. 安裝requests的security extras
參考:https://stackoverflow.com/a/39580231/2510797
pip install -U requests[security]
注意后面的方括號(hào),pip會(huì)安裝三個(gè)security相關(guān)的package:pyopenssl cryptography idna。
試了一下,果然有效,不再報(bào)錯(cuò)。再去讀requests和urllib3的源碼,發(fā)現(xiàn)確實(shí)使用了pyopenssl。具體是怎么用的,還沒(méi)有來(lái)得及分析。
至此個(gè)人覺(jué)得比較好的解決方法基本成型:修改play-scraper的dependency,使用requests[security]來(lái)安裝那三個(gè)安全相關(guān)的包。
另外,系統(tǒng)的openssl版本太舊或太新也可能會(huì)造成問(wèn)題。在目前最新版本的openssl上,該解決方法是有效的。
6.anaconda版的python問(wèn)題
如果你在第一次使用requests時(shí)出現(xiàn)SSL錯(cuò)誤:SSLError("Can’t connect to HTTPS URL because the SSL " urllib3.exceptions.SS,如果你是用的anaconda版的python,那么只要裝python原版就好了,原帖附上:
大致就是說(shuō)anaconda版的python是用的anaconda自己的SSL庫(kù),所以會(huì)報(bào)錯(cuò),換回原版python就不會(huì)有這個(gè)問(wèn)題。
總結(jié):使用開(kāi)源軟件的好處是可以看實(shí)現(xiàn)源碼,花點(diǎn)時(shí)間讀源碼,調(diào)試定位,問(wèn)題基本不難解決。但是文檔有可能不是那么完備,需要進(jìn)行Google或仔細(xì)讀源碼。希望自己的分析思路對(duì)別人有所幫助吧。
總結(jié)
以上是生活随笔為你收集整理的python爬虫ssl错误_Python爬虫:Requests的SSLError:certificate verify failed问题解决方案6条...的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: python运算符_Python运算符总
- 下一篇: python逐个读取字符_玩转pytho