scrapy默认下载器不执行javascript,无法获取vue/react等动态渲染的内容,只能拿到骨架html;必须通过scrapy-playwright插件集成浏览器引擎,将其注入downloader handler,才能真实渲染并精准控制页面行为。

为什么不能直接用 Scrapy 的默认 downloader?
Scrapy 默认基于 Twisted 和 urllib3,不执行 JavaScript,遇到 document.write、fetch 异步加载或 Vue/React 动态渲染的内容时,response.body 里只有骨架 HTML 或空容器。强行解析会拿到空数据或过期的静态占位符。
Playwright 是独立进程驱动浏览器的工具,能真实触发渲染、等待元素、模拟滚动和点击——但它和 Scrapy 的异步调度模型不兼容:Playwright 的 page.goto() 是 async 函数,而 Scrapy 的 start_requests 和 parse 默认是同步流程(除非显式启用 async def)。
必须用 scrapy-playwright 插件,别自己封装
自己用 asyncio.run() 在 parse 里启动 Playwright 会阻塞 Scrapy 的 reactor,导致爬虫卡死或连接复用失败。官方推荐且唯一稳定的方式是使用 scrapy-playwright 插件,它把 Playwright 集成进 Scrapy 的 downloader middleware,所有请求自动走 Chromium/Firefox 实例池。
安装与基础配置:
pip install scrapy-playwright scrapy genspider example example.com
在 settings.py 中启用:
- 设置
DOWNLOAD_HANDLERS覆盖 http/https 协议处理逻辑 - 启用
scrapy_playwright.handler.ScrapyPlaywrightDownloadHandler - 配置
PLAYWRIGHT_BROWSER_TYPE(默认"chromium"),可选"firefox"或"webkit" - 加
twisted.internet.defer.Deferred兼容层,Scrapy 2.8+ 已内置,低版本需确认 Twisted 版本 ≥ 21.2.0
如何在 Request 中控制 Playwright 行为?
不是所有页面都需要等 JS 渲染,盲目开启会拖慢速度。通过 meta 字典传参精细控制:
- 加
"playwright": True启用浏览器渲染(必须) - 用
"playwright_include_page": True把page对象传给callback,方便后续page.screenshot()或page.eval_on_selector() - 设
"playwright_page_methods"执行链式操作,比如:[{"method": "wait_for_selector", "args": ["#content"]}, {"method": "evaluate", "args": ["() => document.title"]}] - 避免写死
page.wait_for_timeout(3000),它不响应网络状态,优先用wait_for_load_state("networkidle")或具体选择器
示例 Request:
yield scrapy.Request(
url="https://example.com/dynamic",
meta={
"playwright": True,
"playwright_page_methods": [
PageMethod("wait_for_selector", "article.item"),
PageMethod("scroll_into_view_if_needed", selector="footer")
]
},
callback=self.parse_dynamic
)
常见报错和内存泄漏点
TimeoutError: Timeout 30000ms exceeded. 最常出现——不是页面慢,而是 selector 写错或等待条件太激进。Playwright 默认超时 30 秒,但 Scrapy 的 DOWNLOAD_TIMEOUT 是另一套机制,两者不联动。
更隐蔽的问题是浏览器实例没释放:
- 没配
PLAYWRIGHT_MAX_PAGES_PER_CONTEXT(默认 1),大量并发请求会撑爆内存 - 忘记在
spider_closed信号里调用crawler.engine.close_spider()触发 Playwright context 销毁 - 用
page.goto()后没显式page.close()(插件已自动处理,但自定义PageMethod里误调用会导致 context 残留) - Linux 下缺共享库,报
Executable doesn't exist at ...:运行playwright install-deps chromium
真正麻烦的是混合场景:同一域名下有些页面要 JS 渲染,有些只要 HTML。这时候不能全局开 DOWNLOAD_HANDLERS,得靠 meta 开关 + 精确的 url 匹配逻辑,否则一半请求走慢通道,吞吐直接腰斩。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











