2017-08-16 246 views
1

代碼應用如何使用python 3中的urllib請求解決SSL握手失敗?

嗨堆垛機,我設計一個網站刮板發送通知基於特定的基於詞的標準的用戶。我已經成功地在一個測試網站上抓了一段時間,但是,當我昨天去運行我的代碼時,出現了一個意外的錯誤,我一直未能解決問題。我仍然不確定爲什麼這個錯誤發生,因爲我的代碼中沒有任何改變 - 這導致我相信網站的某些內容可能已經改變。當我在使用urllib的請求後嘗試讀取網站的內容時,出現錯誤。

守則

url = "http://www.ksl.com" 

import urllib.request 
from urllib.request import Request, urlopen 
from bs4 import BeautifulSoup 

import ssl 
print(ssl.OPENSSL_VERSION) 

req = Request(url, headers={'User-Agent': 'Mozilla/5.0'}) 
html = urlopen(req).read() 
html = html.decode('utf-8') 

錯誤消息

Traceback (most recent call last): 
    File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/urllib/request.py", line 1254, in do_open 
    h.request(req.get_method(), req.selector, req.data, headers) 
    File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/http/client.py", line 1106, in request 
    self._send_request(method, url, body, headers) 
    File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/http/client.py", line 1151, in _send_request 
    self.endheaders(body) 
    File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/http/client.py", line 1102, in endheaders 
    self._send_output(message_body) 
    File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/http/client.py", line 934, in _send_output 
    self.send(msg) 
    File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/http/client.py", line 877, in send 
    self.connect() 
    File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/http/client.py", line 1260, in connect 
    server_hostname=server_hostname) 
    File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/ssl.py", line 377, in wrap_socket 
    _context=self) 
    File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/ssl.py", line 752, in __init__ 
    self.do_handshake() 
    File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/ssl.py", line 988, in do_handshake 
    self._sslobj.do_handshake() 
    File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/ssl.py", line 633, in do_handshake 
    self._sslobj.do_handshake() 
ssl.SSLError: [SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure (_ssl.c:645) 

During handling of the above exception, another exception occurred: 

Traceback (most recent call last): 
    File "PATH TO SCRIPT", line 59, in <module> 
    html = urlopen(req).read() 
    File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/urllib/request.py", line 163, in urlopen 
    return opener.open(url, data, timeout) 
    File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/urllib/request.py", line 472, in open 
    response = meth(req, response) 
    File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/urllib/request.py", line 582, in http_response 
    'http', request, response, code, msg, hdrs) 
    File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/urllib/request.py", line 504, in error 
    result = self._call_chain(*args) 
    File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/urllib/request.py", line 444, in _call_chain 
    result = func(*args) 
    File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/urllib/request.py", line 696, in http_error_302 
    return self.parent.open(new, timeout=req.timeout) 
    File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/urllib/request.py", line 466, in open 
    response = self._open(req, data) 
    File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/urllib/request.py", line 484, in _open 
    '_open', req) 
    File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/urllib/request.py", line 444, in _call_chain 
    result = func(*args) 
    File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/urllib/request.py", line 1297, in https_open 
    context=self._context, check_hostname=self._check_hostname) 
    File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/urllib/request.py", line 1256, in do_open 
    raise URLError(err) 
urllib.error.URLError: <urlopen error [SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure (_ssl.c:645)> 

嘗試我做了修復錯誤

所以我已經安裝了MacPorts的企圖更改python使用的SSL路徑g,這不起作用,我不確定這是否是正確的解決方案路徑。

我把這兩行代碼中看到的是實際上做什麼蟒蛇:

v = sys.version 
print(v) 

import ssl 
print(ssl.OPENSSL_VERSION) 

這兩行給我下面的輸出:

3.5.2 (v3.5.2:4def2a2901a5, Jun 26 2016, 10:47:25) 
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] 
OpenSSL 0.9.8zh 14 Jan 2016 

我認爲這個問題可能是python使用的是默認的OpenSSL版本,無法完成握手,但是我仍然有很多東西需要了解,所以我不完全確定。

請幫我堆垛機,你是我唯一的希望!

回答

0

是的,你的OpenSSL版本太舊了。下面是使用Mac系統的openssl的兩個版本的例子:

$ openssl s_client -connect ksl.com:443 
CONNECTED(00000003) 
2908:error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure:/BuildRoot/Library/Caches/com.apple.xbs/Sources/OpenSSL098/OpenSSL098-64.50.6/src/ssl/s23_clnt.c:593: 

$ /usr/local/Cellar/openssl/1.0.2l/bin/openssl s_client -connect ksl.com:443 
[...] 
Verify return code: 0 (ok) 

如果你安裝python的一個新版本,例如與brew install python3,你應該有更好的運氣:

Python 3.6.2 (default, Jul 17 2017, 16:44:45) 
[GCC 4.2.1 Compatible Apple LLVM 8.1.0 (clang-802.0.42)] on darwin 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import ssl 
>>> ssl.OPENSSL_VERSION 
'OpenSSL 1.0.2l 25 May 2017' 

在這個版本中,你的腳本工作得很好。

+0

嘿基督教謝謝你的迴應!我成功地在終端中運行了「brew install python3」命令,但它似乎沒有更新我擁有的OpenSSL版本(它仍然在打印相同版本)。我認爲這與$ PATH中的事物順序有關,但我不知道如何解決它。 – Whodo