Python自动化如何通过命令并发运行多个Selenium Python文件
Selenium 多脚本并发执行实现方案
Python + Selenium 并发可行性及实现方法
网上流传的Selenium不适配并发任务的说法基本都是踩了资源冲突、实例共享的坑得出的错误结论,只要实现逻辑正确,完全可以编写Python主控脚本调度多个Selenium任务同步并发运行。
绝大多数Selenium并发失败的核心原因只有两个:一是多个并发任务共享同一个WebDriver实例,二是多个浏览器实例抢占同一个用户数据目录触发文件锁。
核心实现规则
- 严格做到实例隔离:每个并发任务必须在自己的执行上下文里独立初始化WebDriver对象,绝对禁止在多进程/多线程间共享同一个driver句柄。使用Chrome/Edge类Chromium内核浏览器时,必须给每个实例分配独立的临时用户数据目录,同时添加
--no-sandbox、--disable-dev-shm-usage启动参数,避免Linux环境下的资源抢占问题。 - 优先用多进程做调度:Python GIL会限制多线程的执行效率,且Selenium的Python绑定本身不是线程安全的,用
multiprocessing或concurrent.futures.ProcessPoolExecutor做调度稳定性最高,每个子进程独立启动浏览器、执行爬取逻辑、结束后主动调用driver.quit()释放资源,避免残留僵尸进程占用内存。 - 禁止全局初始化driver:不要把WebDriver初始化逻辑写在脚本的全局作用域,否则多进程加载脚本时会复用同一个driver句柄直接触发报错,初始化逻辑必须放在单个任务的执行函数内部。
主控调度代码示例
如果要把所有爬取逻辑整合到同一个项目里,可以直接用进程池调度独立任务:
import concurrent.futures import tempfile from selenium import webdriver from selenium.webdriver.chrome.options import Options def run_single_crawl(task_id): # 为每个任务生成独立临时用户目录,彻底规避锁冲突 with tempfile.TemporaryDirectory() as tmp_dir: chrome_opt = Options() chrome_opt.add_argument(f"--user-data-dir={tmp_dir}") chrome_opt.add_argument("--headless=new") chrome_opt.add_argument("--no-sandbox") chrome_opt.add_argument("--disable-dev-shm-usage") # 每个任务独立初始化driver driver = webdriver.Chrome(options=chrome_opt) try: # 替换为实际爬取逻辑 driver.get("https://example.com") return f"任务{task_id}执行完成,获取标题:{driver.title}" finally: # 无论任务成功失败都主动释放资源 driver.quit() if __name__ == "__main__": # 并发数根据机器内存调整,单个无头Chrome实例约占300-800M内存 MAX_WORKERS = 4 task_ids = list(range(MAX_WORKERS)) with concurrent.futures.ProcessPoolExecutor(max_workers=MAX_WORKERS) as executor: for result in executor.map(run_single_crawl, task_ids): print(result)
如果已经写好了多个独立的Selenium脚本文件,不需要修改原有代码,直接用主控脚本通过子进程拉起即可:
import subprocess import concurrent.futures def run_independent_script(script_path): process = subprocess.run( ["python", script_path], capture_output=True, text=True ) return f"脚本{script_path}执行结束,返回码:{process.returncode}" if __name__ == "__main__": # 填入所有需要并发运行的脚本路径 script_list = ["./crawl_task1.py", "./crawl_task2.py", "./crawl_task3.py", "./crawl_task4.py"] with concurrent.futures.ProcessPoolExecutor(max_workers=len(script_list)) as executor: for result in executor.map(run_independent_script, script_list): print(result)
注意:运行独立脚本时需要确认每个脚本内的浏览器实例没有硬编码同一个用户数据目录,否则依然会触发锁冲突导致启动失败。
其他可选技术方案
如果不想手动处理Selenium的资源隔离问题,可以选择更适配并发场景的工具:
- Python生态优先考虑Playwright for Python,天生支持多实例、多上下文并发,内置自动资源隔离逻辑,不需要手动配置临时目录、处理进程锁,并发稳定性远高于Selenium,API设计和Selenium相似度高,迁移成本很低。
- 不需要为了Selenium并发特意更换编程语言,Java、Go、C#等语言的Selenium绑定实现并发的核心逻辑和Python完全一致,都要求每个执行单元独立持有driver实例,不存在某类语言天生支持、某类语言不支持的区别。
- 如果需要突破单机内存限制实现更高并发,可以搭配Selenium Grid或Playwright Grid搭建分布式集群,把浏览器实例调度到多台机器上运行。
Puppeteer 并发支持情况
Puppeteer天生适配多任务并发场景,不存在Selenium那样的适配问题:
- 原生Node.js版Puppeteer对异步并发的支持非常友好,既可以在每个异步任务里独立调用
puppeteer.launch()启动完整的隔离浏览器实例,也可以在同一个浏览器实例下创建多个独立的BrowserContext(相当于轻量无痕会话,资源开销比启动完整浏览器低60%以上),不需要手动处理文件锁、实例冲突问题。 - 运行多个独立Puppeteer脚本的逻辑和Python一致,用进程管理器拉起多个独立Node进程即可,只要每个脚本独立启动自己的浏览器或上下文,就不会出现并发冲突。
- 同等硬件配置下,Puppeteer的单实例资源开销比Selenium低30%左右,能支撑的并发数更高。
内容的提问来源于stack exchange,提问作者lucas lima
相关产品推荐
相关产品推荐

