You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

并发使用Selenium/ChromeDriver时ResponseNotReady错误排查与处理

分析与解决Selenium+Tor代理下的ResponseNotReady: Idle错误

问题1:错误原因分析

这个ResponseNotReady: Idle错误不是你的业务代码逻辑错误,而是底层HTTP连接的状态异常导致的,具体诱因通常有这几个:

  • Selenium的WebDriver和ChromeDriver之间的HTTP连接被意外中断,或者复用了已经失效的连接(比如Tor代理节点切换后,旧连接无法复用)
  • Tor SOCKS代理的连接不稳定,导致WebDriver与ChromeDriver的通信链路出现异常中断
  • 线程池并发复用WebDriver会话时,底层连接池出现了状态不一致(你的代码用队列复用session,并发场景下可能出现连接状态不同步的问题)

简单来说,就是当Selenium底层的HTTP客户端尝试从一个处于Idle(空闲/失效)状态的连接获取响应时,就会抛出这个异常。

问题2:正确处理与恢复方案

最佳处理方式是扩展异常捕获范围,增加重试机制,并在必要时重建WebDriver会话,具体步骤如下:

1. 扩展异常捕获范围

当前你的代码只捕获了WebDriverException,但ResponseNotReady属于http.client模块的异常,不在这个范围内,需要单独导入并捕获:

from http.client import ResponseNotReady

2. 给请求增加重试逻辑

当出现连接类异常时,尝试重试1-2次,避免单次异常导致任务失败:

修改后的_fetch_selenium函数:

def _fetch_selenium(self, url, session, port):
    domain = self.domainFromURL(url)
    with self.locks[port][domain]:
        max_retries = 2  # 设置合理的重试次数
        start_time = datetime.now()
        for attempt in range(max_retries):
            try:
                session.get(url)
                sleep(self.delay)
                return {
                    'url': url,
                    'html': session.page_source,
                    'time': datetime.now() - start_time,
                    'proxy_port': port
                }
            except (selenium_exceptions.WebDriverException, ResponseNotReady) as e:
                print(f"Attempt {attempt+1} for {url} failed: {str(e)}")
                if attempt == max_retries - 1:  # 最后一次尝试失败,返回错误结果
                    sleep(self.delay)
                    return {
                        'url': url,
                        'html': None,
                        'time': datetime.now() - start_time,
                        'proxy_port': port
                    }
                sleep(1)  # 短暂休眠后重试

3. 优化会话复用与重建逻辑

当某个代理端口的会话频繁出现失败时,直接重建WebDriver会话,避免复用失效的连接:

修改后的fetchConcurrent函数关键部分:

# ... 原有代码 ...
if not result['html']:
    socks_port = result['proxy_port']
    print(f"Got no HTML for url {result['url']}, using port {socks_port}.")
    timeouts[socks_port] += 1
    
    if timeouts[socks_port] > MAX_TIMEOUTS_PER_CLIENT:
        tor_client_pool.replaceClient(socks_port)
        # 清理失效会话并重建
        self.killSeleniumSession(session)
        if session in self.sessions:
            self.sessions.remove(session)
        new_session = self.newSeleniumSession(socks_port)
        self.sessions.append(new_session)
        timeouts[socks_port] = 0
        print(f"Replaced Selenium session for port {socks_port} (too many failures)")
    continue
# ... 原有代码 ...

额外优化建议

  • 给WebDriver设置超时时间:在创建会话时添加session.set_page_load_timeout(30)和session.set_script_timeout(30),避免请求挂起导致连接状态异常
  • 定期重建会话:不要长时间复用同一个WebDriver会话,比如每处理N个请求后主动重建,避免Tor代理节点切换带来的连接失效
  • 检查Tor客户端状态:确保Tor客户端运行稳定,没有频繁的节点切换或者网络中断

内容的提问来源于stack exchange,提问作者J. Taylor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 06:26:14