我有一个简单的屏幕抓取例程,它使用代理抓取服务 (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/