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

Python多线程使用Selenium异常,JS渲染爬虫求解决方案

问题分析与解决方案

首先,你遇到的核心问题是Selenium的WebDriver对象并非线程安全——多个线程共用同一个driver实例时,会导致操作互相干扰,这就是为什么你的脚本是逐个执行且只打印最后一个URL标题的原因。而使用Multiprocessing时崩溃,大多是因为ChromeDriver在多进程环境下的沙箱机制或资源冲突问题。

下面是具体的解决方法和替代建议:

一、修复Threading + Selenium的问题

解决思路很简单:给每个线程分配独立的WebDriver实例,不要共用同一个driver。修改后的代码示例如下:

import threading as th
from bs4 import BeautifulSoup
from seleniumwire import webdriver
from selenium.webdriver.chrome.options import Options

def getinf(url_):
    # 每个线程创建独立的Chrome配置和Driver实例
    options = Options()
    prefs = {'profile.default_content_setting_values': {'images': 2,'popups': 2, 'geolocation': 2, 'notifications': 2, 'auto_select_certificate': 2, 'fullscreen': 2, 'mouselock': 2, 'mixed_script': 2, 'media_stream': 2, 'media_stream_mic': 2, 'media_stream_camera': 2, 'protocol_handlers': 2, 'ppapi_broker': 2, 'automatic_downloads': 2, 'midi_sysex': 2, 'push_messaging': 2, 'ssl_cert_decisions': 2, 'metro_switch_to_desktop': 2, 'protected_media_identifier': 2, 'app_banner': 2, 'site_engagement': 2, 'durable_storage': 2}}
    options.add_experimental_option('prefs', prefs)
    # 添加避免崩溃的参数(多线程/进程通用)
    options.add_argument('--headless=new')  # 无头模式,减少资源占用,可选
    options.add_argument('--no-sandbox')
    options.add_argument('--disable-dev-shm-usage')
    
    driver = webdriver.Chrome(options=options)
    driver.set_page_load_timeout(50000)
    
    try:
        driver.get(url_)
        soup = BeautifulSoup(driver.page_source, 'html5lib')
        print(f"URL: {url_}, 标题: {soup.select('title')[0].text}")
    except Exception as e:
        print(f"处理{url_}时出错: {str(e)}")
    finally:
        driver.quit()  # 用完必须关闭,释放资源

if __name__ == "__main__":
    print('爬虫启动')
    urls = 'https://google.com https://youtube.com'
    threads = []
    
    for url in urls.split():
        t = th.Thread(target=getinf, args=(url,))
        threads.append(t)
        t.start()
    
    # 等待所有线程执行完成
    for t in threads:
        t.join()
    
    print('爬虫结束')

关键修改点:

  • 把driver的创建移到getinf函数内部,每个线程都有自己的浏览器实例
  • 添加--no-sandbox和--disable-dev-shm-usage参数,避免Chrome在受限环境下崩溃
  • 增加异常捕获和driver.quit(),确保资源正常释放

二、解决Multiprocessing崩溃问题

如果想用多进程,核心思路和线程一致:每个进程独立创建WebDriver,同时保留上述的Chrome参数。示例代码:

import multiprocessing as mp
from bs4 import BeautifulSoup
from seleniumwire import webdriver
from selenium.webdriver.chrome.options import Options

def getinf(url_):
    options = Options()
    prefs = {'profile.default_content_setting_values': {'images': 2,'popups': 2, 'geolocation': 2, 'notifications': 2, 'auto_select_certificate': 2, 'fullscreen': 2, 'mouselock': 2, 'mixed_script': 2, 'media_stream': 2, 'media_stream_mic': 2, 'media_stream_camera': 2, 'protocol_handlers': 2, 'ppapi_broker': 2, 'automatic_downloads': 2, 'midi_sysex': 2, 'push_messaging': 2, 'ssl_cert_decisions': 2, 'metro_switch_to_desktop': 2, 'protected_media_identifier': 2, 'app_banner': 2, 'site_engagement': 2, 'durable_storage': 2}}
    options.add_experimental_option('prefs', prefs)
    options.add_argument('--headless=new')
    options.add_argument('--no-sandbox')
    options.add_argument('--disable-dev-shm-usage')
    
    driver = webdriver.Chrome(options=options)
    driver.set_page_load_timeout(50000)
    
    try:
        driver.get(url_)
        soup = BeautifulSoup(driver.page_source, 'html5lib')
        print(f"URL: {url_}, 标题: {soup.select('title')[0].text}")
    except Exception as e:
        print(f"处理{url_}时出错: {str(e)}")
    finally:
        driver.quit()

if __name__ == "__main__":
    print('爬虫启动')
    urls = ['https://google.com', 'https://youtube.com']
    
    # 使用进程池管理
    with mp.Pool(processes=2) as pool:
        pool.map(getinf, urls)
    
    print('爬虫结束')

三、更适合的替代库推荐

针对需要JS渲染的网站,Playwright是目前比Selenium更优的选择,它由微软维护,API更简洁,原生支持并发,对动态内容的处理更稳定。

Playwright示例代码(同步+多进程)

from playwright.sync_api import sync_playwright
import multiprocessing as mp

def crawl_with_playwright(url_):
    with sync_playwright() as p:
        # 启动浏览器,支持无头/有头模式
        browser = p.chromium.launch(headless=True)
        page = browser.new_page()
        try:
            page.goto(url_, timeout=50000)
            title = page.title()
            print(f"URL: {url_}, 标题: {title}")
            # 如需解析页面,可使用page.content()获取HTML,再用BeautifulSoup处理
            # soup = BeautifulSoup(page.content(), 'html5lib')
        except Exception as e:
            print(f"处理{url_}时出错: {str(e)}")
        finally:
            browser.close()

if __name__ == "__main__":
    print('爬虫启动')
    urls = ['https://google.com', 'https://youtube.com']
    
    with mp.Pool(processes=2) as pool:
        pool.map(crawl_with_playwright, urls)
    
    print('爬虫结束')

Playwright的优势:

  • 自动处理浏览器实例的创建和销毁,无需手动配置大量Chrome参数
  • 支持异步API,可结合asyncio实现更高效率的并发
  • 对动态渲染内容的支持更完善,内置等待机制,减少超时问题
  • 支持Chrome、Firefox、Safari等多浏览器

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 10:09:08