urllib无法读取https

时间:2014-11-29 23:06:49

标签: python-3.x https urllib

(Python 3.4.2) 有人能帮我用urllib获取https页面吗?我花了好几个小时试图解决这个问题。

这是我正在尝试做的事情(非常基本):

import urllib.request
url = "".join((baseurl, other_string, midurl, query))
response = urllib.request.urlopen(url)
html = response.read()

这是我运行时的错误输出:

File "./script.py", line 124, in <module>
    response = urllib.request.urlopen(url)
  File "/usr/lib/python3.4/urllib/request.py", line 153, in urlopen
    return opener.open(url, data, timeout)
  File "/usr/lib/python3.4/urllib/request.py", line 455, in open
    response = self._open(req, data)
  File "/usr/lib/python3.4/urllib/request.py", line 478, in _open
    'unknown_open', req)
  File "/usr/lib/python3.4/urllib/request.py", line 433, in _call_chain
    result = func(*args)
  File "/usr/lib/python3.4/urllib/request.py", line 1244, in unknown_open
    raise URLError('unknown url type: %s' % type)
urllib.error.URLError: <urlopen error unknown url type: 'https>

我也尝试使用data = None无济于事:

response = urllib.request.urlopen(url, data=None)

我也试过这个:

import urllib.request, ssl
https_sslv3_handler = urllib.request.HTTPSHandler(context=ssl.SSLContext(ssl.PROTOCOL_SSLv3))
opener = urllib.request.build_opener(https_sslv3_handler)
urllib.request.install_opener(opener)
resp = opener.open(url)
html = resp.read().decode('utf-8')
print(html)

此^脚本发生了类似的错误,其中错误发生在“resp = ...”行,并抱怨'https'是未知的网址类型。

Python是在我的计算机(Arch Linux)上使用SSL支持编译的。我已经尝试过几次重新安装python3和openssl,但这没有用。我没有尝试完全卸载python然后重新安装,因为我还需要在我的计算机上卸载很多其他程序。

任何人都知道发生了什么事吗?

- - - - - - - - 编辑

在Andrew Stevlov的回答帮助下,我明白了。我的网址中有一个“:”,我猜urllib不喜欢这样。我用“%3A”替换它,现在它正在工作。非常感谢你们!

4 个答案:

答案 0 :(得分:3)

仔细检查您的编辑选项,看起来您的包装盒有问题。

至少以下代码适用于我:

from urllib.request import urlopen
resp = urlopen('https://github.com')
print(resp.read())

答案 1 :(得分:1)

urllib.error.URLError: <urlopen error unknown url type: 'https>

错误消息中的'https而非https表示您没有尝试http://请求,而是'https://请求当然不存在。检查您构建URL的方式。

答案 2 :(得分:1)

这可能会有所帮助

忽略SSL证书错误

ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE

url = input('Enter - ')
html = urllib.request.urlopen(url, context=ctx).read()

答案 3 :(得分:1)

当我尝试使用https打开url时,我遇到了相同的错误,而http却没有错误。

>>> from urllib.request import urlopen
>>> urlopen('http://google.com')
<http.client.HTTPResponse object at 0xb770252c>
>>> urlopen('https://google.com')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.7/urllib/request.py", line 222, in urlopen
    return opener.open(url, data, timeout)
  File "/usr/local/lib/python3.7/urllib/request.py", line 525, in open
    response = self._open(req, data)
  File "/usr/local/lib/python3.7/urllib/request.py", line 548, in _open
    'unknown_open', req)
  File "/usr/local/lib/python3.7/urllib/request.py", line 503, in _call_chain
    result = func(*args)
  File "/usr/local/lib/python3.7/urllib/request.py", line 1387, in unknown_open
    raise URLError('unknown url type: %s' % type)
urllib.error.URLError: <urlopen error unknown url type: https>

这是在Ubuntu 16.04上使用Python 3.7完成的。本机Ubuntu默认在/ usr / bin中使用Python 3.5,以前我已经下载了源并将其升级到3.7 in /usr/local/bin。 3.5没有错误的事实表明在3.7中没有正确安装可执行文件/ usr / bin / openssl,这在下面也很明显:

>>> import ssl
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.7/ssl.py", line 98, in <module>
    import _ssl             # if we can't import it, let the error propagate
ModuleNotFoundError: No module named '_ssl'

通过咨询此link,我将3.7源目录的Modules / Setup.dist中的SSL = / usr / local / ssl更改为SSL = / usr,并将其cp到Setup中,然后重建了Python 3.7。

$ ./configure
$ make
$ make install

现在已解决:

>>> import ssl
>>> ssl.OPENSSL_VERSION
'OpenSSL 1.0.2g  1 Mar 2016'
>>> urlopen('https://www.google.com') 
<http.client.HTTPResponse object at 0xb74c4ecc>
>>> urlopen('https://www.google.com').read()
b'<!doctype html>...

和3.7已成功符合OpenSSL支持。请注意,只有将Ubuntu的命令“ openssl version”加载到Python中才能完成。