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

使用Selenium(Python)网页爬取时多线程输出异常问题

多线程爬取u.gg时所有线程返回首个链接结果的原因排查

1. WebDriver实例未做线程隔离

Selenium的WebDriver对象本身不是线程安全的,如果所有线程复用同一个浏览器实例,线程间的页面操作会互相干扰。比如第一个线程打开首个链接后,其他线程的页面导航请求可能被阻塞或覆盖,最终所有线程都在首个链接的页面上执行爬取逻辑,导致结果一致。

解决办法:

  • 每个线程独立创建WebDriver实例,在gather_summoner_info函数内部初始化driver,执行完爬取后关闭:
    def gather_summoner_info(link):
        driver = webdriver.Chrome()
        try:
            driver.get(link)
            # 爬取逻辑
        finally:
            driver.quit()
    

2. 任务提交时的参数绑定错误

如果在循环提交线程任务时,错误地使用了延迟绑定的变量(比如用lambda包裹任务但未正确捕获参数),或函数内部误用全局变量替代传入参数,会导致所有线程使用同一个链接值。若全局变量被意外设置为首个链接,就会出现所有线程返回首个结果的问题。

比如错误写法:

# 错误:lambda捕获的是link的引用,若全局link被篡改会导致参数异常
with ThreadPoolExecutor() as executor:
    futures = [executor.submit(lambda: gather_summoner_info(link)) for link in links]

解决办法:

  • 直接传递参数到submit方法,避免lambda延迟绑定:
    with ThreadPoolExecutor() as executor:
        futures = [executor.submit(gather_summoner_info, link) for link in links]
    
  • 确保gather_summoner_info函数内部使用传入的参数,而非全局变量。

3. 结果存储的线程不安全

如果爬取结果被存入全局变量(比如全局列表),且未加锁保护,多个线程同时写入时可能出现数据覆盖。若首个线程的结果先被写入,后续线程的写入操作因竞态条件被覆盖,最终所有结果都显示为首个链接的内容。

解决办法:

  • 使用线程安全的容器存储结果,比如queue.Queue,或者在写入结果时加锁:
    from threading import Lock
    
    result_lock = Lock()
    results = []
    
    def gather_summoner_info(link):
        # 爬取逻辑得到data
        with result_lock:
            results.append(data)
    

4. 页面加载的竞态条件

当多个线程共用同一个driver时,第一个线程调用driver.get(link1)后,页面还未加载完成,其他线程就调用driver.get(link2),但WebDriver无法同时处理多个导航请求,后续的导航可能被忽略,导致所有线程都在link1的页面上执行爬取。

解决办法:

  • 严格做到线程与WebDriver实例一一对应,每个线程拥有独立的浏览器窗口,避免跨线程操作同一个driver。

内容的提问来源于stack exchange,提问作者Jack

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 12:15:39