使用proxpy配合Python-Selenium时如何解决SSL文件缺失错误?
我尝试使用Proxpy监控Python-Selenium测试过程中的所有请求,所用Python代码如下:
from selenium import webdriver PROXY = "0.0.0.0:9999" webdriver.DesiredCapabilities.FIREFOX['proxy'] = { "httpProxy":PROXY, "ftpProxy":PROXY, "sslProxy":PROXY, "proxyType":"MANUAL" } driver = webdriver.Firefox() driver.get("http://www.google.co.in") driver.quit()
启动代理的命令为:
python proxpy/proxpy/proxpy.py -p 9999
运行测试脚本时出现如下错误(macOS环境):
Exception happened during processing of request from ('127.0.0.1', 64667)
Traceback (most recent call last):
File "/Users/adietz/anaconda/lib/python2.7/SocketServer.py", line 596, in process_request_thread
self.finish_request(request, client_address)
File "/Users/adietz/anaconda/lib/python2.7/SocketServer.py", line 331, in finish_request
self.RequestHandlerClass(request, client_address, self)
File "/Users/adietz/Projects/Invest/browsermob/proxpy/proxpy/core.py", line 56, in init
SocketServer.StreamRequestHandler.init(self, request, client_address, server)
File "/Users/adietz/anaconda/lib/python2.7/SocketServer.py", line 652, in init
self.handle()
File "/Users/adietz/Projects/Invest/browsermob/proxpy/proxpy/core.py", line 137, in handle
res = self.doCONNECT(host, port, req)
File "/Users/adietz/Projects/Invest/browsermob/proxpy/proxpy/core.py", line 188, in doCONNECT
ssl_version = ssl.PROTOCOL_SSLv23, do_handshake_on_connect = False)
File "/Users/adietz/anaconda/lib/python2.7/ssl.py", line 933, in wrap_socket
ciphers=ciphers)
File "/Users/adietz/anaconda/lib/python2.7/ssl.py", line 544, in init
self._context.load_cert_chain(certfile, keyfile)
IOError: [Errno 2] No such file or directory
Linux机器上会出现等效错误:
Exception happened during processing of request from ('127.0.0.1', 35348)
Traceback (most recent call last):
File "/usr/lib/python2.7/SocketServer.py", line 596, in process_request_thread
self.finish_request(request, client_address)
File "/usr/lib/python2.7/SocketServer.py", line 331, in finish_request
self.RequestHandlerClass(request, client_address, self)
File "/home/adietz/Projects/Invest/browsermob-proxy/proxpy/proxpy/core.py", line 56, in init
SocketServer.StreamRequestHandler.init(self, request, client_address, server)
File "/usr/lib/python2.7/SocketServer.py", line 652, in init
self.handle()
File "/home/adietz/Projects/Invest/browsermob-proxy/proxpy/proxpy/core.py", line 137, in handle
res = self.doCONNECT(host, port, req)
File "/home/adietz/Projects/Invest/browsermob-proxy/proxpy/proxpy/core.py", line 188, in doCONNECT
ssl_version = ssl.PROTOCOL_SSLv23, do_handshake_on_connect = False)
File "/usr/lib/python2.7/ssl.py", line 933, in wrap_socket
ciphers=ciphers)
File "/usr/lib/python2.7/ssl.py", line 544, in init
self._context.load_cert_chain(certfile, keyfile)
IOError: [Errno 2] No such file or directory
请问如何修复该错误?如何避免此类问题?以及如何实现请求与响应的监控?
错误原因分析
从报错信息里的self._context.load_cert_chain(certfile, keyfile)和IOError: [Errno 2] No such file or directory可以直接定位问题:Proxpy作为中间人代理处理HTTPS请求时,找不到所需的SSL证书和密钥文件。Proxpy需要自签名证书来解密HTTPS流量,默认情况下它会尝试加载指定路径的证书文件,如果未生成或者路径配置错误,就会触发这个报错。
修复步骤
1. 生成Proxpy所需的SSL证书和密钥
Proxpy自带了证书生成脚本,先运行它创建必要的证书文件:
# 进入Proxpy的工具目录(路径根据你的实际安装位置调整) cd proxpy/proxpy/utils # 运行证书生成脚本 python create_cert.py
这个脚本会生成proxy.crt(证书文件)和proxy.key(密钥文件),默认会存放在Proxpy的核心代码目录(比如proxpy/proxpy/下)。
2. 启动Proxpy时指定证书路径(可选,若证书不在默认路径)
如果生成的证书不在Proxpy默认搜索的路径,启动时需要显式指定证书和密钥的位置:
python proxpy/proxpy/proxpy.py -p 9999 --cert /path/to/proxy.crt --key /path/to/proxy.key
把/path/to/替换成你实际生成证书的目录路径即可。
3. 配置Firefox信任Proxpy的自签名证书
因为是自签名证书,Firefox会默认拦截HTTPS请求,需要手动信任该证书:
- 打开Firefox,访问
about:preferences#privacy - 找到「证书」板块,点击「查看证书」
- 切换到「证书机构」标签页,点击「导入」
- 选择生成的
proxy.crt文件,勾选「信任由此证书机构标识的网站」,完成导入操作
4. 优化Selenium代理配置(可选)
你的Selenium配置可以更简洁,同时避免本地请求走代理,调整后的代码如下:
from selenium import webdriver from selenium.webdriver.firefox.options import Options PROXY_HOST = "0.0.0.0" PROXY_PORT = 9999 options = Options() # 设置代理类型为手动 options.set_preference("network.proxy.type", 1) # 配置HTTP代理 options.set_preference("network.proxy.http", PROXY_HOST) options.set_preference("network.proxy.http_port", PROXY_PORT) # 配置HTTPS代理 options.set_preference("network.proxy.ssl", PROXY_HOST) options.set_preference("network.proxy.ssl_port", PROXY_PORT) # 本地地址不走代理 options.set_preference("network.proxy.no_proxies_on", "localhost,127.0.0.1") driver = webdriver.Firefox(options=options) driver.get("http://www.google.co.in") driver.quit()
如何避免此类问题
- 启动Proxpy前必生成证书:每次新部署Proxpy或更换运行环境时,先执行证书生成脚本,不要跳过这一步
- 固定证书路径:把生成的证书和密钥放到Proxpy核心代码所在的目录,或者启动时始终显式指定路径,避免因路径变化导致找不到文件
- 预配置浏览器信任证书:提前创建Firefox自定义配置文件,在配置文件中预加载信任Proxpy的证书,这样自动化测试时就不需要手动重复信任操作
实现请求与响应的监控
Proxpy本身提供了多种方式来监控请求和响应:
- 查看控制台默认输出:启动Proxpy后,它会自动在终端打印每个请求的方法、URL、状态码、请求头、响应头信息,你可以直接查看
- 启用DEBUG日志获取详细信息:启动Proxpy时添加
--log-level DEBUG参数,会输出完整的请求体、响应体等调试信息:python proxpy/proxpy/proxpy.py -p 9999 --cert /path/to/proxy.crt --key /path/to/proxy.key --log-level DEBUG - 自定义代码记录请求响应:如果需要更个性化的监控(比如保存到文件),可以修改
proxpy/core.py中的请求处理方法,例如在handle()或doGET()/doPOST()方法中添加代码:# 读取请求体示例 content_length = int(self.headers.get('Content-Length', 0)) request_body = self.rfile.read(content_length) print(f"[REQUEST BODY] {request_body}") # 读取响应体示例(在doCONNECT或其他请求处理方法中) response_body = conn.recv(4096) print(f"[RESPONSE BODY] {response_body}")
内容的提问来源于stack exchange,提问作者Alex

