无限滚动页面导致爬虫内存暴涨的根本原因是DOM节点累积、JavaScript上下文未释放及网络响应对象滞留。需避免保留ElementHandle、及时清空DOM、限制滚动次数、禁用非必要资源加载并主动关闭页面。

为什么无限滚动页面会让爬虫内存暴涨
根本原因是爬虫在模拟滚动时不断累积 DOM 节点、JavaScript 上下文和未释放的网络响应对象。特别是用 selenium 或 playwright 时,每轮 page.evaluate() 或 driver.execute_script() 都可能触发新节点挂载,而旧节点若没被显式清理或页面未触发垃圾回收,就会滞留在内存中。更隐蔽的是,某些站点的无限滚动逻辑会持续监听 scroll 事件并注册新回调,导致闭包引用链无法释放。
用 page.evaluate() 获取内容后立即丢弃 DOM 引用
Playwright 用户常犯的错误是把整个 document.querySelectorAll() 结果存成 Python 列表,这会让 Playwright 后台保持对所有匹配元素的句柄引用,阻止浏览器端 GC。正确做法是只提取需要的文本或属性,不保留 ElementHandle。
- ❌ 错误:
elements = page.evaluate("() => Array.from(document.querySelectorAll('.item'))")(返回的是序列化后的数组,看似安全,但若节点含大量嵌套 HTML,JSON 序列化本身也吃内存) - ✅ 正确:
items = page.evaluate("() => Array.from(document.querySelectorAll('.item')).map(el => ({ title: el.querySelector('h3')?.textContent, link: el.querySelector('a')?.href }))") - 执行完立刻用
page.evaluate("() => { while (document.body.firstChild) document.body.removeChild(document.body.firstChild); }")清空临时插入的占位节点(如有)
限制滚动次数 + 主动终止无新增数据的加载循环
靠“滚动到底部”这种模糊条件极易陷入死循环——有些页面底部永远有“加载中”占位符,或接口返回空数组却不更新状态。必须引入明确的退出机制。
- 记录每次滚动后新增的条目数,连续 2–3 次返回 0 条时
break - 设置硬性上限:比如最多滚动 20 次,或总耗时超 60 秒就
page.close() - 检查网络请求是否真正完成:用
page.wait_for_response()监听分页接口,超时则中断,避免等待一个永不返回的请求拖住整个上下文
关闭自动缓存与禁用图片/字体加载(Playwright/Selenium)
默认情况下,浏览器会缓存已加载资源并在内存中保留下载的图片、字体二进制数据,对长时间运行的滚动爬虫来说,这部分可能占到数百 MB。这不是 JS 内存泄漏,而是浏览器进程自身的资源堆积。
立即学习“Python免费学习笔记(深入)”;
- Playwright:启动时加
args=["--disable-images", "--disable-fonts"],或用context.set_extra_http_headers({"Accept": "text/html"})减少响应体积 - Selenium:配置
options.add_argument("--blink-settings=imagesEnabled=false"),并设置profile.set_preference("permissions.default.image", 2) - 关键动作:每次滚动前调用
page.clear_cache()(Playwright 1.40+ 支持)或手动page.goto("about:blank", wait_until="commit")触发页面重置


















