如何固定复用两个Selenium浏览器实例分别加载不同链接
固定复用2个浏览器实例的实现方案
你现有代码反复新开浏览器窗口的原因很直接:webdriver.Chrome()初始化逻辑写在了任务函数内部,每提交一次任务就会触发一次浏览器启动,自然会生成新窗口。
利用线程池复用工作线程的特性就可以实现固定数量实例的复用:每个工作线程仅在第一次领到任务时初始化1个专属浏览器实例,后续该线程的所有加载任务都复用这个实例。由于你设置了max_workers=2,整个程序生命周期只会启动2个Chrome窗口,完全满足需求。
可直接运行的代码
import concurrent.futures import threading from selenium import webdriver links = [ 'https://en.wikipedia.org/wiki/File:Mechanitis_Polymnia_Chrysalis.jpg', 'https://en.wikipedia.org/wiki/File:William_Cornwallis_as_Admiral_(cropped).jpg', 'https://en.wikipedia.org/wiki/File:Battle_of_Saint_Charles.jpg', 'https://en.wikipedia.org/wiki/File:Stephen_Curry_Shooting_(cropped)_(cropped).jpg' ] # 线程本地存储,为每个工作线程绑定独立的driver实例 thread_local = threading.local() # 存所有初始化过的driver,方便最后统一回收 all_drivers = [] drivers_lock = threading.Lock() def get_driver(): # 当前线程没有绑定driver时才初始化新实例 if not hasattr(thread_local, 'driver'): chrome_options = webdriver.ChromeOptions() driver = webdriver.Chrome(options=chrome_options) thread_local.driver = driver with drivers_lock: all_drivers.append(driver) return thread_local.driver def load_page(url): driver = get_driver() driver.get(url) print(f'对应浏览器实例加载完成: {url}') if __name__ == '__main__': with concurrent.futures.ThreadPoolExecutor(max_workers=2) as executor: # 提交所有任务并等待执行完成 futures = [executor.submit(load_page, link) for link in links] concurrent.futures.wait(futures) # 所有任务跑完后统一关闭浏览器,需要保留窗口可以注释掉这部分 for driver in all_drivers: driver.quit()
注意事项
- 不要把单个driver实例共享给多个线程使用:Selenium的driver本身不是线程安全的,同一时间一个driver只能处理一个页面操作,给每个线程绑定专属实例的方式可以完全规避线程安全问题
- 不要在单个任务逻辑里调用
driver.quit(),否则后续该线程领到新任务时会找不到可用的浏览器实例 - 如果需要调整浏览器实例数量,直接修改
max_workers参数即可,程序会自动生成对应数量的浏览器实例,不需要改其他逻辑 - 任务分配由线程池自动调度,两个浏览器会依次处理分配到的链接,不会出现重复创建实例的问题
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

