【问题标题】:Pandas raises ssl.CertificateError when using method read_html for HTTPS resources当对 HTTPS 资源使用方法 read_html 时,Pandas 引发 ssl.CertificateError
【发布时间】:2018-11-30 20:21:21
【问题描述】:

我有一个使用 url 地址读取网页内容的代码。

之前我的代码运行良好,现在站点安全证书出现问题。为了解决IE的问题,我完成了将证书导入到可信站点,问题解决了。

但是当我运行这段代码时:

df = pd.read_html(i,header=0)[0]

我收到一个错误:

Traceback (most recent call last):
  File "D:\Distrib\Load_Data_from_Flat_ver_1.py", line 95, in <module>
    df = pd.read_html(i,header=0)[0]
  File "C:\Program Files\Python36\lib\site-packages\pandas\io\html.py", line 915, in read_html
    keep_default_na=keep_default_na)
  File "C:\Program Files\Python36\lib\site-packages\pandas\io\html.py", line 749, in _parse
    raise_with_traceback(retained)
  File "C:\Program Files\Python36\lib\site-packages\pandas\compat\__init__.py", line 385, in raise_with_traceback
    raise exc.with_traceback(traceback)
ssl.CertificateError: hostname '10.89.174.12' doesn't match 'localhost'

谁能帮我解决这个问题?

【问题讨论】:

  • 欢迎您,您能否提供mcve 以帮助我们了解正在发生的事情。乍一看,您的服务器公用名似乎不匹配。

标签: python pandas ssl python-requests urllib


【解决方案1】:

什么是错误

阅读 ssl 包的 PSL 文档,您会发现发生此特定错误的示例。

>>> cert = {'subject': ((('commonName', 'example.com'),),)}
>>> ssl.match_hostname(cert, "example.com")
>>> ssl.match_hostname(cert, "example.org")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/py3k/Lib/ssl.py", line 130, in match_hostname
ssl.CertificateError: hostname 'example.org' doesn't match 'example.com'

检查服务器公用名时,第二次检查失败。这正是你的情况。

Python 路径

参考熊猫documentation

io : str 或类似文件 URL、类似文件的对象或包含 HTML 的原始字符串。 请注意,lxml 只接受 http、ftp 和文件 url 协议。如果你 有一个以“https”开头的网址,您可以尝试删除“s”。

您无法使用 read_html 方法从 HTTPS 读取。

要绕过这个问题,首先使用 PSL over HTTPS 下载资源,而不验证 SSL 上下文:

from urllib import request
import ssl

url="https://example.com/data.html"
context = ssl._create_unverified_context()
response = request.urlopen(url, context=context)
html = response.read()

然后用 Pandas 处理它:

import pandas as pd
df = pd.read_html(html)

创建有效上下文

正如@AlastairMcCormack 指出的那样:

context = ssl._create_unverified_context() 只能用于 localhost 或测试。

如果在不验证 SSL 上下文的情况下访问资源可以解决您的问题,那么是时候创建一个有效的上下文introsnippets)以安全地获取您的资源。

服务器路径

您还可以创建一个新证书,其中公用名与服务器域(或其 IP)匹配。这里localhost 似乎来自发送到生产服务器的开发证书,这无法正常工作。

无论如何,这一点并不能解决read_html 不处理HTTPS 连接的事实。

【讨论】:

  • 很好的答案,但应该强调context = ssl._create_unverified_context() 只能用于本地主机或测试
  • @AlastairMcCormack 我会相应地更新我的答案
猜你喜欢
  • 2017-05-17
  • 2019-11-07
  • 1970-01-01
  • 2020-01-11
  • 1970-01-01
  • 2021-09-02
  • 1970-01-01
  • 2017-01-07
  • 1970-01-01
相关资源
最近更新 更多