如何在Python脚本因Selenium WebDriver get()冻结时重启脚本
Selenium WebDriver get()方法无响应时的自动重启方案
已知Selenium的WebDriver get()方法存在无异常冻结的问题,常规方案(如设置set_page_load_timeout)无效时,子进程隔离+超时监控是最稳妥的重启实现方案——子进程能彻底隔离卡死的浏览器进程,避免主线程被阻塞。
核心思路
将浏览器初始化与页面访问逻辑封装为独立函数,通过子进程执行该函数,主线程监控子进程运行时长:
- 若子进程在指定超时内完成任务,正常推进后续逻辑
- 若超时,强制终止子进程、清理残留浏览器进程,再重新初始化浏览器并重试
完整实现代码
from webdriver_manager.chrome import ChromeDriverManager from selenium.webdriver.chrome.service import Service from selenium.webdriver import Chrome, ChromeOptions from selenium.webdriver.support.ui import WebDriverWait import multiprocessing import time import psutil TIMEOUT = 10 RETRY_TIMES = 3 # 最大重试次数 DATA = {"user_data_dir": "./chrome_profile"} # 替换为你的用户数据目录 def run_browser_task(url): """封装浏览器初始化与页面访问逻辑""" options = ChromeOptions() options.add_experimental_option('excludeSwitches', ['enable-logging']) options.add_argument(f'user-data-dir={DATA["user_data_dir"]}') chrome_driver = ChromeDriverManager().install() driver = Chrome(service=Service(chrome_driver), options=options) driver.maximize_window() wait = WebDriverWait(driver, TIMEOUT) try: driver.get(url) # 可添加页面加载验证逻辑,比如检查标题或元素 print(f"页面加载成功:{driver.title}") except Exception as e: print(f"访问出错:{str(e)}") finally: driver.quit() def kill_child_processes(parent_pid): """清理残留的浏览器子进程""" try: parent = psutil.Process(parent_pid) children = parent.children(recursive=True) for child in children: child.kill() print("已清理残留进程") except Exception as e: print(f"清理进程出错:{str(e)}") def main(): target_url = 'https://www.stackoverflow.com/' retry_count = 0 while retry_count < RETRY_TIMES: print(f"第 {retry_count+1} 次尝试访问页面") # 创建子进程执行浏览器任务 process = multiprocessing.Process(target=run_browser_task, args=(target_url,)) process.start() # 等待指定超时时间 process.join(TIMEOUT) if process.is_alive(): # 子进程仍运行,判定为get()冻结 print("页面访问超时,终止进程并重试") process.terminate() process.join() # 清理残留浏览器进程 kill_child_processes(process.pid) retry_count += 1 time.sleep(2) # 重试前短暂等待 else: # 任务完成,退出循环 print("任务执行完成") break if retry_count >= RETRY_TIMES: print(f"已达到最大重试次数 {RETRY_TIMES},任务失败") if __name__ == "__main__": main()
关键说明
- 子进程隔离:用
multiprocessing.Process启动浏览器任务,避免主线程被卡死的get()阻塞 - 超时监控:通过
process.join(TIMEOUT)等待任务完成,超时则判定为冻结 - 进程清理:用
psutil库清理浏览器残留进程,防止内存泄漏 - 重试机制:设置最大重试次数,避免无限循环
内容的提问来源于stack exchange,提问作者Jeffrey Lebowski
相关产品推荐
相关产品推荐

