如何使用python 3中的urllib请求解决SSL握手失败?
问题描述:
代码应用如何使用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版本,无法完成握手,但是我仍然有很多东西需要了解,所以我不完全确定。
请帮我堆垛机,你是我唯一的希望!
答
是的,你的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'
在这个版本中,你的脚本工作得很好。
嘿基督教谢谢你的回应!我成功地在终端中运行了“brew install python3”命令,但它似乎没有更新我拥有的OpenSSL版本(它仍然在打印相同版本)。我认为这与$ PATH中的事物顺序有关,但我不知道如何解决它。 – Whodo