python - Python 中的 URL 请求失败 - 找不到 SSL 证书

标签 python python-3.x ssl

我有一个简单的屏幕抓取例程,它使用代理抓取服务 (Scrapinghub) 通过 BeautifulSoup 获取 HTML 页面:

def make_soup(self,current_url):
    soup = None
    r = requests.get(current_url, proxies=self.proxies, auth=self.proxy_auth,
         verify='static/crawlera-ca.crt')
    if r.status_code == 200:
        soup = bs4.BeautifulSoup(r.text, "html.parser")
        if soup:
            return soup
    return False

当我在 http://站点上运行它时,它工作正常。

当我在 https://站点上运行它时,它会返回:

Traceback (most recent call last):
  File "/home/danny/Documents/virtualenvs/AskArbyEnv/lib/python3.5/site-packages/requests/packages/urllib3/util/ssl_.py", line 295, in ssl_wrap_socket
    context.load_verify_locations(ca_certs, ca_cert_dir)
FileNotFoundError: [Errno 2] No such file or directory

更奇怪的是,当我在访问同一个 https://站点的单元测试中运行它时,它会起作用。

单元测试和运行代码之间唯一不同的是我附加到传递给“make_soup”的 URL 的搜索词。每个生成的 URL 都是格式正确的,我可以在浏览器中访问它们。

这让我认为这与缺少 SSL 证书无关。那为什么它好像在提示找不到证书文件呢?

最佳答案

通过在调用 requests.get 时指定 verify='static/crawlera-ca.crt',表示您访问的所有站点都必须有证书由 crawlera-ca.crt 签名。如果您的代理没有即时重写请求/响应和服务器证书(它不应该,但请检查下面的更新),那么您对 ​​https 站点的所有请求都会失败。

此外,如果您仔细阅读错误消息,您会发现磁盘上什至没有那个 crawlera-ca.crt 文件。

要解决您的问题,只需删除 verify 参数。这样requests will use the default , certifi bundle (对于 requests>=2.4.0)。对于非侵入式代理,这是正确的解决方案。或者,如果确实需要,您可以将一些您信任的 CA 证书添加到本地 certifi 存储区,但要非常小心添加哪些证书。

更新。看起来 Crawlera 代理毕竟是一个中间人! 糟糕的 Crawlera,糟糕,糟糕,糟糕!

$ curl -vvv -x proxy.crawlera.com:8010 --cacert crawlera-ca.crt https://google.com/
[...snip...]
* Proxy replied OK to CONNECT request
* found 1 certificates in crawlera-ca.crt
* found 697 certificates in /etc/ssl/certs
* ALPN, offering http/1.1
* SSL connection using TLS1.2 / ECDHE_RSA_AES_256_GCM_SHA384
*    server certificate verification OK
*    server certificate status verification SKIPPED
*    common name: google.com (matched)
*    server certificate expiration date OK
*    server certificate activation date OK
*    certificate public key: RSA
*    certificate version: #1
*    subject: CN=google.com
*    start date: Sat, 08 Jul 2017 13:33:53 GMT
*    expire date: Tue, 06 Jul 2027 13:33:53 GMT
*    issuer: C=IE,ST=Munster,L=Cork,O=ScrapingHub,OU=Leading Technology and Professional Services,CN=Crawlera CA,EMAIL=support@scrapinghub.com
*    compression: NULL

请注意 CN=google.com 是由 O=ScrapingHub,CN=Crawlera CA 发布的。

这意味着 Crawlera/ScrapingHub 正在重新加密您向目标网址发出的每个请求,并读取您与该网站交换的所有私有(private)和敏感数据!我知道这是他们缓存原始请求并为所有抓取同一站点的用户节省一些带宽的唯一方法,也是检查内容合法性的唯一方法,但仍然如此。他们应该将 is 放在他们的常见问题解答中的某个地方,但我不确定他们是否这样做。

关于python - Python 中的 URL 请求失败 - 找不到 SSL 证书,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44981771/

相关文章:

ssl - 如何在加特林中关闭 TLSv1.3?

php - 413 请求实体太大 - Nginx 1.8.1

python - 删除 pandas 中的第一行

python - 删除出现在大括号之间的换行符

python - 我想模拟打开一个现有的测试文件,对其应用一个函数进行测试,但不更改文件的实际内容

python-2.7 - Python - 在两个列表中获取重复匹配项

Python TIC TAC TOE 跳轮

ssl - 在 Apache Kafka 中禁用 TLS 1.0、TLS 1.1

python - PyQt4:重新排序 QDialogBu​​ttonBox 中的确定和取消按钮

python - 将一张表的内容复制到django中的另一张表