
本文详解 selenium 在频繁打开/关闭浏览器标签页时出现内存持续增长的根本原因,并提供基于定期重启 webdriver 实例的稳定、可落地的内存管理策略。
本文详解 selenium 在频繁打开/关闭浏览器标签页时出现内存持续增长的根本原因,并提供基于定期重启 webdriver 实例的稳定、可落地的内存管理策略。
在使用 Selenium 自动化采集网页数据时,若需批量处理数百个 URL(例如通过 window.open() 动态创建标签页),开发者常遇到一个典型瓶颈:即使调用 driver.close() 关闭标签页,Chrome 进程的内存占用仍持续攀升,且几乎不释放。如示例代码所示,循环 25 次开闭标签页后,任务管理器中 Chrome 的内存占用可能增长数百 MB——这并非由 Python 端缓存的数据导致,而是 Chromium 渲染进程与 WebDriver 会话间存在资源回收延迟或未完全清理的上下文(如 JS 执行环境、网络栈、GPU 缓存等)。driver.close() 仅关闭当前窗口句柄,但底层 Blink 渲染器、V8 实例及部分共享内存区域并未被及时归还操作系统。
✅ 推荐解决方案:分批复用 + 定期重置 WebDriver
最有效、经生产验证的实践是 避免长期持有单个 WebDriver 实例,转而采用「固定批次 + 显式退出 + 重建」策略。例如每处理 20–50 个页面后调用 driver.quit(),再新建实例继续执行。该方式虽引入毫秒级启动开销,却能彻底切断内存累积链路,保障整体稳定性。
以下为优化后的参考实现:
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import time
def create_driver():
options = Options()
options.add_argument("--no-sandbox")
options.add_argument("--disable-dev-shm-usage")
options.add_argument("--disable-gpu")
options.add_argument("--incognito") # 减少扩展/缓存干扰
# 可选:限制内存用量(Chromium 参数)
options.add_argument("--memory-pressure-threshold-mb=512")
return webdriver.Chrome(options=options)
def scrape_batch(urls, batch_size=30):
driver = create_driver()
base_url = "https://edition.cnn.com/"
try:
driver.get(base_url)
for i, url in enumerate(urls):
if i > 0 and i % batch_size == 0:
# 每 batch_size 个页面后重置驱动
driver.quit()
print(f"✅ Batch {i//batch_size} completed. Restarting WebDriver...")
driver = create_driver()
driver.get(base_url)
# 复用首个 tab,避免频繁 window.open
driver.get(url)
# ✨ 此处插入您的数据提取逻辑
# e.g., title = driver.title; content = driver.find_element(...).text
time.sleep(0.3) # 防反爬节流,非必需
finally:
driver.quit() # 确保最终释放
# 使用示例:模拟 600 个目标 URL
urls = ["https://edition.cnn.com/"] * 600
scrape_batch(urls, batch_size=40)⚠️ 关键注意事项
- 不要依赖 window.open() + close() 模拟多标签页:这是内存泄漏的主因。现代 Chromium 对动态标签页的资源隔离不完善,尤其在无用户交互场景下。
- 禁用无关功能:--disable-gpu、--disable-dev-shm-usage 等参数可显著降低基础内存 footprint。
- 避免全局 driver 实例:切勿在整个脚本生命周期内复用同一 driver 对象处理全部请求。
- 监控与兜底:可在循环中加入内存检查(如 psutil.Process().memory_info().rss),超阈值时主动 quit() 并重建。
- 替代思路(进阶):对极致性能要求场景,可考虑无头浏览器池(如 Playwright 的 browser.new_context())或 HTTP 客户端(Requests + BeautifulSoup)直取静态内容,绕过浏览器渲染层。
综上,Selenium 的内存问题本质是架构约束而非 Bug——它设计初衷并非高并发标签页调度。接受 quit()/new 的轻量重启成本,是平衡稳定性与资源消耗的最优解。 将“单实例长连接”思维切换为“短生命周期批处理”,即可从容应对 600+ 页面规模的自动化采集任务。










