Python爬虫遇SSLError: HTTPSConnectionPool错误的解决求助
解决Python爬虫SSL证书验证失败问题
问题描述
我正在搭建第一个Python网络爬虫,已按教程安装对应库并复制了代码:
import requests from bs4 import BeautifulSoup req = requests.get("https://www.geeksforgeeks.org/") soup = BeautifulSoup(req.content, "html.parser") print(soup.prettify())
运行时出现SSL证书验证失败的错误,完整错误信息如下:
错误 回溯(最近的调用在最前) ~/anaconda3/lib/python3.6/site-packages/urllib3/contrib/pyopenssl.py 在 wrap_socket(self, sock, server_side, do_handshake_on_connect, suppress_ragged_eofs, server_hostname) 440 尝试: --> 441 cnx.do_handshake() 442 捕获 OpenSSL.SSL.WantReadError: ~/anaconda3/lib/python3.6/site-packages/OpenSSL/SSL.py 在 do_handshake(self) 1715 result = _lib.SSL_do_handshake(self._ssl) -> 1716 self._raise_ssl_error(self._ssl, result) 1717 ~/anaconda3/lib/python3.6/site-packages/OpenSSL/SSL.py 在 _raise_ssl_error(self, ssl, result) 1455 否则: -> 1456 _raise_current_error() 1457 ~/anaconda3/lib/python3.6/site-packages/OpenSSL/_util.py 在 exception_from_error_queue(exception_type) 53 ---> 54 抛出 exception_type(errors) 55 错误: [('SSL 例程', 'ssl3_get_server_certificate', '证书验证失败')] 在处理上述异常期间,又发生了另一个异常: SSLError 回溯(最近的调用在最前) ~/anaconda3/lib/python3.6/site-packages/urllib3/connectionpool.py 在 urlopen(self, method, url, body, headers, retries, redirect, assert_same_host, timeout, pool_timeout, release_conn, chunked, body_pos, **response_kw) 600 body=body, headers=headers, --> 601 chunked=chunked) 602 ~/anaconda3/lib/python3.6/site-packages/urllib3/connectionpool.py 在 _make_request(self, conn, method, url, timeout, chunked, **httplib_request_kw) 345 尝试: --> 346 self._validate_conn(conn) 347 捕获 (SocketTimeout, BaseSSLError) 作为 e: ~/anaconda3/lib/python3.6/site-packages/urllib3/connectionpool.py 在 _validate_conn(self, conn) 849 如果 没有 getattr(conn, 'sock', None): # AppEngine 可能没有 `.sock` --> 850 conn.connect() 851 ~/anaconda3/lib/python3.6/site-packages/urllib3/connection.py 在 connect(self) 325 server_hostname=hostname, --> 326 ssl_context=context) 327 ~/anaconda3/lib/python3.6/site-packages/urllib3/util/ssl_.py 在 ssl_wrap_socket(sock, keyfile, certfile, cert_reqs, ca_certs, server_hostname, ssl_version, ciphers, ssl_context, ca_cert_dir) 328 如果 HAS_SNI: # 平台特定: 启用SNI的OpenSSL --> 329 return context.wrap_socket(sock, server_hostname=server_hostname) 330 ~/anaconda3/lib/python3.6/site-packages/urllib3/contrib/pyopenssl.py 在 wrap_socket(self, sock, server_side, do_handshake_on_connect, suppress_ragged_eofs, server_hostname) 447 捕获 OpenSSL.SSL.Error 作为 e: --> 448 抛出 ssl.SSLError('握手失败: %r' % e) 449 break SSLError: ("握手失败: Error([('SSL routines', 'ssl3_get_server_certificate', 'certificate verify failed')],)",) 在处理上述异常期间,又发生了另一个异常: MaxRetryError 回溯(最近的调用在最前) ~/anaconda3/lib/python3.6/site-packages/requests/adapters.py 在 send(self, request, stream, timeout, verify, cert, proxies) 439 retries=self.max_retries, --> 440 timeout=timeout 441 ) ~/anaconda3/lib/python3.6/site-packages/urllib3/connectionpool.py 在 urlopen(self, method, url, body, headers, retries, redirect, assert_same_host, timeout, pool_timeout, release_conn, chunked, body_pos, **response_kw) 638 retries = retries.increment(method, url, error=e, _pool=self, --> 639 _stacktrace=sys.exc_info()[2]) 640 retries.sleep() ~/anaconda3/lib/python3.6/site-packages/urllib3/util/retry.py 在 increment(self, method, url, response, error, _pool, _stacktrace) 387 如果 new_retry.is_exhausted(): --> 388 抛出 MaxRetryError(_pool, url, error or ResponseError(cause)) 389 MaxRetryError: HTTPSConnectionPool(host='www.geeksforgeeks.org', port=443): 超过最大重试次数,URL: / (由 SSLError(SSLError("握手失败: Error([('SSL routines', 'ssl3_get_server_certificate', 'certificate verify failed')],)",),) 引起) 在处理上述异常期间,又发生了另一个异常: SSLError 回溯(最近的调用在最前) <ipython-input-2-ed1606e0fa56> 在 <module>() 1 import requests 2 from bs4 import BeautifulSoup ----> 3 req = requests.get("https://www.geeksforgeeks.org/") 4 soup = BeautifulSoup(req.content, "html.parser") 5 print(soup.prettify()) ~/anaconda3/lib/python3.6/site-packages/requests/api.py 在 get(url, params, **kwargs) 70 71 kwargs.setdefault('allow_redirects', True) ---> 72 return request('get', url, params=params, **kwargs) 73 74 ~/anaconda3/lib/python3.6/site-packages/requests/api.py 在 request(method, url, **kwargs) 56 # 某些情况下,这会导致循环引用,在其他情况下看起来像内存泄漏。 57 with sessions.Session() as session: ---> 58 return session.request(method=method, url=url, **kwargs) 59 60 ~/anaconda3/lib/python3.6/site-packages/requests/sessions.py 在 request(self, method, url, params, data, headers, cookies, files, auth, timeout, allow_redirects, proxies, hooks, stream, verify, cert, json) 506 } 507 send_kwargs.update(settings) --> 508 resp = self.send(prep, **send_kwargs) 509 510 return resp ~/anaconda3/lib/python3.6/site-packages/requests/sessions.py 在 send(self, request, **kwargs) 616 617 # 发送请求 --> 618 r = adapter.send(request, **kwargs) 619 620 # 请求的总耗时(大约) ~/anaconda3/lib/python3.6/site-packages/requests/adapters.py 在 send(self, request, stream, timeout, verify, cert, proxies) 504 如果 isinstance(e.reason, _SSLError): 505 # 这个分支适用于urllib3 v1.22及更高版本。 --> 506 抛出 SSLError(e, request=request) 507 508 抛出 ConnectionError(e, request=request) SSLError: HTTPSConnectionPool(host='www.geeksforgeeks.org', port=443): 超过最大重试次数,URL: / (由 SSLError(SSLError("握手失败: Error([('SSL routines', 'ssl3_get_server_certificate', 'certificate verify failed')],)",),) 引起)
解决方案
临时测试方案(不推荐生产环境)
- 在
requests.get()中添加verify=False参数,跳过证书校验:
req = requests.get("https://www.geeksforgeeks.org/", verify=False)
注意:该操作会关闭SSL安全校验,存在被中间人攻击的风险,仅用于临时测试。
永久解决(推荐)
- 更新系统CA证书:根据操作系统更新根证书包:
- Linux:安装或更新
ca-certificates包(如apt install ca-certificates或yum install ca-certificates) - macOS:通过「钥匙串访问」应用更新系统证书,或执行
brew install ca-certificates - Windows:通过系统更新获取最新的根证书
- Linux:安装或更新
- 升级依赖库:运行以下命令更新
requests和urllib3到最新版本,修复已知的证书处理问题:
pip install --upgrade requests urllib3
- 指定自定义CA证书:如果你的环境使用自定义证书,可以通过
verify参数指定证书文件路径:
req = requests.get("https://www.geeksforgeeks.org/", verify="/path/to/your/ca_cert.pem")
内容的提问来源于stack exchange,提问作者Juan
相关产品推荐
相关产品推荐

