Selenium循环10-15次后报Timed out receiving message from renderer错误
故障根因
抛出selenium.common.exceptions.TimeoutException: Message: timeout: Timed out receiving message from renderer: 300.000不是普通的元素等待超时,是Chrome渲染进程和WebDriver通信中断、进程僵死导致的,属于典型的长循环Selenium任务资源泄漏问题,跑10-15次才触发完全符合内存累积溢出的特征:
- 每次循环直接调用
driver.get()跳转页面,没有主动回收渲染进程、页面JS上下文、缓存的残留资源,循环次数叠加后Chrome内存占用持续上涨,最终渲染进程无响应,WebDriver等待300秒收不到渲染进程返回就抛出该异常。 - 原有嵌套
try/finally逻辑存在缺陷:如果定位回复框步骤抛出异常,代码依然会强制执行查找提交按钮并点击的逻辑,触发大量无效等待,进一步加速驱动僵死。 - 原代码使用
presence_of_element_located作为元素等待条件,仅判断元素存在于DOM树,不保证元素可交互,容易出现点击无效、流程卡住的问题;同时没有设置页面加载超时、异常兜底逻辑,页面偶发的第三方资源加载失败就会把整个进程卡成死锁状态。
修复方案
按以下步骤调整代码即可稳定运行,核心改动点见注释:
- 初始化Chrome驱动时添加防泄漏、降卡顿的启动参数,调整页面加载策略减少无效等待
- 修正错误的异常捕获逻辑,统一处理流程异常,出错时主动清理页面资源
- 增加定时重启浏览器的兜底逻辑,从根源解决长时间运行的内存累积问题
优化后的完整代码:
from selenium import webdriver from selenium.webdriver.chrome.options import Options import time from datetime import datetime from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By # Chrome启动配置,减少内存占用、避免渲染进程后台被挂起 chrome_options = Options() chrome_options.add_argument("--disable-renderer-backgrounding") chrome_options.add_argument("--disable-background-timer-throttling") chrome_options.add_argument("--disable-backgrounding-occluded-windows") chrome_options.add_argument("--disable-extension") chrome_options.add_argument("--disk-cache-size=0") chrome_options.add_argument("--media-cache-size=0") # 页面加载策略改为eager,DOM就绪即可操作,无需等待图片、广告等第三方资源加载完成 chrome_options.page_load_strategy = 'eager' def init_driver(): """封装驱动初始化逻辑,方便重启时调用""" drv = webdriver.Chrome(options=chrome_options) drv.set_page_load_timeout(60) drv.set_script_timeout(30) return drv driver = init_driver() thread = "替换为你的目标帖子地址" MAGENTA = "\033[35m" # 原有终端打印颜色常量 for i in range(100000000): now = datetime.now() current_time = now.strftime("%H:%M:%S") try: driver.get(thread) # 等待回复框可交互后再输入内容 reply_box = WebDriverWait(driver, 30).until(EC.element_to_be_clickable((By.ID, "message"))) reply_box.clear() reply_box.send_keys("random test string") # 等待提交按钮可点击后执行点击 post_reply = WebDriverWait(driver, 30).until(EC.element_to_be_clickable((By.ID, "quick_reply_submit"))) post_reply.click() # 等待提交按钮失效(页面跳转/刷新),确认回复提交成功 WebDriverWait(driver, 30).until(EC.staleness_of(post_reply)) print(MAGENTA + f"[{current_time}] Autobump #" + str(i + 1)) except Exception as e: print(f"[{current_time}] 第{i+1}次执行出错: {str(e)},清理资源后继续") # 异常时清理残留标签页、cookie,回收僵死的渲染进程 driver.execute_script("window.open('');") time.sleep(1) driver.switch_to.window(driver.window_handles[-1]) driver.close() driver.switch_to.window(driver.window_handles[0]) driver.delete_all_cookies() continue # 每执行10次操作强制重启浏览器,彻底清除内存累积,是长稳运行的核心兜底 if (i + 1) % 10 == 0: print(f"[{current_time}] 已完成10次操作,重启浏览器清理内存") driver.quit() time.sleep(2) driver = init_driver() time.sleep(1860)
关键注意点
- 不要依赖Chrome启动参数完全解决内存泄漏问题,Chrome在长时间执行Selenium自动化操作时必然会出现内存上涨,定时重启是工业界通用的最稳妥方案,没有之一。
- 替换元素等待条件为
element_to_be_clickable,可以避免90%以上的元素存在但点击无效的偶发问题。 - 异常分支的资源清理逻辑可以避免单次出错导致整个循环终止,不需要人工介入即可自动恢复运行。
内容的提问来源于stack exchange,提问作者Penderdrill
相关产品推荐
相关产品推荐

