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
相关产品推荐
相关产品推荐

