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

使用Selenium爬虫时遇MemoryError与RuntimeError问题求助

解决Selenium爬虫的MemoryError和RuntimeError: can't start new thread问题

我帮你分析下这个问题,你遇到的MemoryError和RuntimeError: can't start new thread,核心原因是Selenium的ChromeDriver长时间运行后,浏览器进程的内存持续累积、线程资源被耗尽——哪怕你清空了Python里的列表,浏览器本身的缓存、DOM元素、后台线程没被正确释放,还是会撑爆资源。结合你的代码,给你几个落地的解决方案:

一、给Chrome加启动参数,大幅降低内存占用

Chrome默认会加载很多不必要的功能(比如图片、扩展、缓存),这些都会占用大量内存。启动时添加以下参数,能砍掉大部分冗余消耗:

from selenium import webdriver
from selenium.webdriver.chrome.options import Options

chrome_options = Options()
# 禁用图片加载(如果不需要爬取图片的话)
chrome_options.add_argument('--blink-settings=imagesEnabled=false')
# 禁用缓存,避免累积页面缓存
chrome_options.add_argument('--disable-cache')
# 禁用浏览器扩展
chrome_options.add_argument('--disable-extensions')
# 启用无头模式(不需要可视化界面时用,内存占用更低)
chrome_options.add_argument('--headless=new')
# 禁用GPU加速,减少渲染资源消耗
chrome_options.add_argument('--disable-gpu')
# Windows下可选:禁用沙箱,避免额外线程开销
chrome_options.add_argument('--no-sandbox')

# 用配置好的参数启动driver
driver = webdriver.Chrome(options=chrome_options)

二、定期重启浏览器,彻底释放资源

哪怕加了参数,Chrome运行几十页后还是会有内存泄漏。最直接的办法是每处理一定数量的店铺/页面后,关闭当前浏览器进程,重新启动并登录,彻底清空资源:

store_count = 0
login_url = 'https://login.aliexpress.com/'

for index, row in df.iterrows():
    store_count += 1
    # 每处理10个店铺就重启一次浏览器(数量可以根据自己的情况调整)
    if store_count % 10 == 0:
        driver.quit()
        # 重新初始化driver并完成登录流程
        driver = webdriver.Chrome(options=chrome_options)
        driver.implicitly_wait(30)
        driver.get(login_url)
        time.sleep(3)
        driver.switch_to.frame('alibaba-login-box')
        driver.find_element_by_id('fm-login-id').send_keys('你的账号')
        driver.find_element_by_id('fm-login-password').send_keys('你的密码')
        driver.find_element_by_id('fm-login-submit').click()
        time.sleep(3)
        driver.switch_to.default_content()
    
    # 后续的店铺页面爬取代码...

三、换掉driver.back(),改用新标签页处理商品页

你现在用driver.back()回到列表页,这个操作会保留之前商品页的DOM和状态,时间久了会积累大量无用数据。改用新标签页打开商品页,处理完就关闭标签页,能避免这个问题:

# 遍历商品链接时,用新标签页打开
for link in links:
    # 执行JS打开新标签页
    driver.execute_script(f"window.open('{link}');")
    # 切换到新打开的标签页
    driver.switch_to.window(driver.window_handles[-1])
    
    time.sleep(2)
    soup1 = BeautifulSoup(driver.page_source, 'html.parser')
    # 处理商品详情数据...
    
    # 关闭当前标签页
    driver.close()
    # 切回列表页的标签页
    driver.switch_to.window(driver.window_handles[0])

四、优化数据存储逻辑,减少内存中的数据堆积

你现在是攒够500条数据再写入CSV,这会让price、prod_name这些列表在内存里越来越大。改成每处理完一个商品就直接写入CSV,彻底避免内存堆积:

# 提前打开CSV文件,保持写入状态
with open('output.csv', 'a', newline='') as f:
    writer = csv.writer(f)
    # 写表头(如果文件是新的)
    # writer.writerow(['商品名称', '价格', '链接', '规格'])
    
    for index, row in df.iterrows():
        # 处理店铺列表页...
        links = [link.get_attribute('href') for link in driver.find_elements_by_xpath("//div[@id='node-gallery']/div[5]/div/div/ul/li/div[2]/h3/a")]
        
        for link in links:
            # 打开新标签页处理商品...
            # 处理完后组装当前商品的数据
            current_prod_data = (prod_name_t, div_b_text + 'Ł', prod_name_l + 'Ł', item_specs_replace)
            # 直接写入CSV
            writer.writerow(current_prod_data)

五、排查线程泄漏的补充建议

RuntimeError: can't start new thread通常是因为进程的线程数达到了系统上限。除了上面的重启浏览器方案,你还可以:

  • 打开任务管理器(Windows)或htop(Linux),查看Chrome进程的线程数,如果持续增长,说明确实有线程泄漏,重启是最有效的解决办法。
  • 避免在代码中手动创建额外线程,Selenium本身已经在后台管理大量线程,额外线程会加速耗尽资源。

六、用工具定位内存泄漏点(可选)

如果还是不确定哪里在耗内存,可以用tracemalloc工具分析内存使用情况,找出最耗内存的代码段:

import tracemalloc

# 启动内存跟踪
tracemalloc.start()

# 你的爬虫代码...

# 生成内存快照并打印Top10内存消耗点
snapshot = tracemalloc.take_snapshot()
top_stats = snapshot.statistics('lineno')
print("Top 10内存消耗点:")
for stat in top_stats[:10]:
    print(stat)

按照上面的方案调整后,你的爬虫应该能稳定运行完所有网站了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:46:01