Scrapy+Splash:爬取动态渲染的 JavaScript 页面
·
Scrapy+Splash:爬取动态渲染的 JavaScript 页面
当网页内容通过 JavaScript 动态渲染时,传统爬虫无法直接获取完整数据。Scrapy(Python 爬虫框架)结合 Splash(JavaScript 渲染服务)可解决此问题。以下是完整实现流程:
1. 核心原理
- Scrapy:负责爬虫逻辑、请求调度和数据提取
- Splash:作为轻量级浏览器渲染引擎,执行 JavaScript 并返回渲染后的 HTML
- 交互流程:
graph LR A[Scrapy] -->|发送渲染请求| B[Splash] B -->|执行JS渲染| C[目标网站] C -->|返回完整HTML| B B -->|返回渲染结果| A
2. 环境配置
(1) 安装 Splash 服务
# 通过 Docker 运行 Splash
docker run -p 8050:8050 scrapinghub/splash
(2) 安装 Scrapy 依赖
pip install scrapy scrapy-splash
(3) Scrapy 配置 (settings.py)
# 启用 Splash 中间件
DOWNLOADER_MIDDLEWARES = {
'scrapy_splash.SplashMiddleware': 725
}
# 设置 Splash 服务地址
SPLASH_URL = 'http://localhost:8050'
# 添加去重过滤器
DUPEFILTER_CLASS = 'scrapy_splash.SplashAwareDupeFilter'
3. 爬虫实现
(1) 创建 Splash 请求
import scrapy
from scrapy_splash import SplashRequest
class DynamicSpider(scrapy.Spider):
name = 'js_spider'
def start_requests(self):
url = 'https://example.com/dynamic-page'
yield SplashRequest(
url,
callback=self.parse,
# 关键参数:等待渲染完成
args={'wait': 2.5},
endpoint='render.html'
)
(2) 处理渲染结果
def parse(self, response):
# 提取渲染后的数据
title = response.css('h1::text').get()
dynamic_content = response.xpath('//div[@id="dynamic-area"]/text()').get()
yield {
'title': title,
'content': dynamic_content
}
4. 高级渲染控制
(1) 执行自定义 JavaScript
yield SplashRequest(
url,
args={
'lua_source': """
function main(splash)
splash:go(splash.args.url)
splash:wait(1)
splash:runjs('document.querySelector("button.more").click()')
splash:wait(2)
return splash:html()
end
"""
}
)
(2) 处理 AJAX 加载
args={
'wait': 0.5,
'resource_timeout': 10, # 资源加载超时时间
'images': 0, # 禁用图片加速
}
5. 常见问题解决
| 问题现象 | 解决方案 |
|---|---|
| 数据加载不全 | 增加 wait 参数值 (0.5-3秒) |
| 点击事件未触发 | 使用 runjs 模拟点击操作 |
| 内存泄漏 | 设置 splash:set_viewport_full() |
| 反爬虫检测 | 添加 splash:set_user_agent() |
6. 性能优化建议
- 并发控制:在
settings.py中调整CONCURRENT_REQUESTS = 8 # 根据服务器性能调整 - 缓存复用:启用 Splash 缓存
args={'wait': 1, 'cache_args': ['lua_source']} - 请求过滤:使用
SplashAwareDupeFilter避免重复渲染
提示:对于复杂 SPA(单页应用),建议结合
scrapy-playwright方案,但 Splash 在资源消耗和部署便捷性上仍有优势。
更多推荐
所有评论(0)