【问题标题】:urllib cannot read httpsurllib 无法读取 https
【发布时间】:2014-11-29 23:06:49
【问题描述】:

(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”是未知的 url 类型。

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

有人知道发生了什么吗?

-----编辑-----

感谢 Andrew Stevlov 的回答,我想通了。我的网址中有一个“:”,我猜 urllib 不喜欢这样。我用“%3A”替换了它,现在它可以工作了。非常感谢大家!!!

【问题讨论】:

标签: python-3.x https urllib


【解决方案1】:

仔细检查您的编译选项,您的盒子似乎有问题。

至少以下代码对我有用:

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

【讨论】:

  • 哇,这对我也有用!我想到了。我的网址中有一个“:”,我猜 urllib 不喜欢这样。我用“%3A”替换了它,现在它可以工作了。非常感谢大家!!!
  • 我再次检查过——仍然有效。你遇到了什么异常?
【解决方案2】:

这可能会有所帮助

忽略 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】:
    urllib.error.URLError: <urlopen error unknown url type: 'https>
    

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

    【讨论】:

      【解决方案4】:

      当我尝试使用 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 没有错误的事实表明可执行文件 /usr/bin/openssl 在 3.7 中没有正确安装,这在下面也很明显:

      >>> 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 版本”加载到 Python 之前,它是不完整的。

      【讨论】:

        猜你喜欢
        • 2016-02-13
        • 1970-01-01
        • 2013-11-11
        • 1970-01-01
        • 2020-04-13
        • 2022-12-05
        • 1970-01-01
        • 2014-06-01
        • 1970-01-01
        相关资源
        最近更新 更多