当前位置: 首页 > news >正文

Scrapy与Splash结合爬取JavaScript渲染页面

在网络爬虫的开发过程中,我们经常会遇到一类 “棘手” 的目标网站 —— 基于 JavaScript 动态渲染的页面。这类网站不会在初始 HTML 中直接返回完整数据,而是通过前端脚本异步加载、渲染内容。传统的 Scrapy 爬虫直接解析响应文本,往往只能拿到空壳结构,无法获取有效信息。此时,将ScrapySplash结合,就成为了攻克这类网站的高效方案。

一、核心原理:为什么需要 Splash?

Scrapy 是 Python 生态中功能强大的爬虫框架,它以高效的异步请求、灵活的数据处理流程著称,但它的短板在于无法执行 JavaScript 代码。当爬虫向目标网站发送请求时,得到的响应是未经渲染的原始 HTML,其中动态加载的列表、数据、按钮等元素都尚未生成。

Splash 则是一个专门用于渲染 JavaScript 页面的轻量级工具,它本质是一个带有 HTTP API 的无界面浏览器,基于 Qt5 和 WebKit 内核。Splash 可以模拟真实浏览器的行为:加载页面、执行 JS 脚本、等待 DOM 渲染完成,然后返回渲染后的完整 HTML 页面,甚至可以截取页面截图、获取页面加载的 HAR 数据。

Scrapy 与 Splash 的结合逻辑非常清晰:

  1. Scrapy 不再直接向目标网站发送请求,而是将请求参数发送给 Splash 服务;
  2. Splash 接收请求后,模拟浏览器加载目标页面,完成 JS 渲染;
  3. Splash 将渲染后的 HTML 页面返回给 Scrapy;
  4. Scrapy 对渲染后的 HTML 进行解析,提取目标数据。

二、环境准备:安装与配置

在开始编写爬虫之前,我们需要完成基础环境的搭建,主要分为Splash 服务部署Python 依赖安装两步。

2.1 部署 Splash 服务

Splash 支持多种部署方式,最推荐的是Docker 容器部署,这种方式无需处理复杂的依赖关系,一键即可启动服务。

  1. 确保本地已安装 Docker 环境,执行以下命令拉取 Splash 镜像:

    bash

    运行

    docker pull scrapinghub/splash
  2. 启动 Splash 容器,映射端口(默认端口为 8050):

    bash

    运行

    docker run -p 8050:8050 scrapinghub/splash
  3. 验证服务是否启动成功:打开浏览器访问http://localhost:8050,若能看到 Splash 的测试页面,则说明部署成功。

2.2 安装 Python 依赖库

需要安装scrapy-splash库,它是 Scrapy 与 Splash 通信的桥梁,提供了专门的下载器中间件和请求类。

bash

运行

pip install scrapy-splash

三、Scrapy 项目配置:接入 Splash

创建一个新的 Scrapy 项目后,我们需要修改settings.py配置文件,让 Scrapy 能够使用 Splash 服务。

3.1 核心配置项

打开项目根目录下的settings.py,添加或修改以下配置:

python

运行

# 1. 配置Splash服务的地址 SPLASH_URL = 'http://localhost:8050' # 2. 启用Splash相关的下载器中间件 DOWNLOADER_MIDDLEWARES = { 'scrapy_splash.SplashCookiesMiddleware': 723, 'scrapy_splash.SplashMiddleware': 725, 'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware': 810, } # 3. 配置Splash的去重过滤器 DUPEFILTER_CLASS = 'scrapy_splash.SplashAwareDupeFilter' # 4. 配置缓存存储(可选,用于缓存Splash的响应) HTTPCACHE_STORAGE = 'scrapy_splash.SplashAwareFSCacheStorage'

这些配置的核心作用是让 Scrapy 的请求走 Splash 通道,并处理 Splash 响应的去重和缓存问题。

四、编写爬虫:实战爬取 JS 渲染页面

接下来,我们以一个简单的 JS 渲染页面为例,编写完整的爬虫代码。假设目标网站的动态数据是通过 Ajax 加载的商品列表,我们需要提取商品名称和价格。

4.1 创建爬虫文件

在项目的spiders目录下创建js_spider.py,代码如下:

python

运行

import scrapy from scrapy_splash import SplashRequest class JsRenderSpider(scrapy.Spider): name = 'js_render_spider' allowed_domains = ['example.com'] # 替换为目标域名 start_urls = ['https://example.com/js-render-page'] # 替换为目标URL # 定义Splash的Lua脚本:用于控制页面渲染过程 lua_script = """ function main(splash, args) -- 设置页面加载超时时间 splash:set_timeout(10) -- 加载目标页面 assert(splash:go(args.url)) -- 等待页面渲染完成(等待5秒,或等待指定元素出现) assert(splash:wait(5)) -- 返回渲染后的页面HTML return { html = splash:html(), -- 可选:返回页面截图 -- png = splash:png(), } end """ def start_requests(self): for url in self.start_urls: # 使用SplashRequest替代scrapy.Request yield SplashRequest( url=url, callback=self.parse, endpoint='execute', # 指定Splash的执行端点 args={ 'lua_source': self.lua_script, # 传入Lua脚本 'wait': 2 # 额外的等待参数 } ) def parse(self, response): # 解析渲染后的HTML(与普通Scrapy解析方式一致) products = response.xpath('//div[@class="product-item"]') for product in products: yield { 'name': product.xpath('.//h3/text()').get().strip(), 'price': product.xpath('.//span[@class="price"]/text()').get().strip() }

4.2 代码核心解析

  1. SplashRequest 替代 Request:这是与普通爬虫的核心区别,SplashRequest会将请求发送到 Splash 服务,并携带 Lua 脚本控制渲染流程。
  2. Lua 脚本的作用:Lua 脚本是 Splash 的灵魂,它可以实现复杂的页面操作:
    • splash:go(args.url):加载目标 URL;
    • splash:wait(5):等待 5 秒,确保 JS 脚本执行完毕、数据加载完成;
    • splash:html():获取渲染后的 HTML 源码;
    • 除此之外,还可以实现click(点击元素)、fill(填写表单)、scroll_position(滚动页面)等操作。
  3. 解析响应:经过 Splash 渲染后的响应,与普通 HTML 响应的解析方式完全一致,我们可以使用 XPath 或 CSS 选择器轻松提取数据。

五、高级技巧:优化渲染与爬取效率

在实际爬取过程中,我们需要根据目标网站的特性优化爬虫,避免出现超时、漏数据等问题。

5.1 智能等待:替代固定等待时间

固定的splash:wait(5)不够灵活,页面加载快时会浪费时间,加载慢时会导致渲染不完整。我们可以通过等待指定元素出现来优化:

lua

-- 等待class为"product-list"的元素出现,超时时间10秒 assert(splash:wait_for_element('div.product-list', 10))

5.2 处理动态加载的分页

对于无限滚动的分页页面,可以通过 Lua 脚本模拟滚动操作,触发更多数据加载:

lua

function main(splash, args) splash:go(args.url) splash:wait(2) -- 模拟向下滚动3次,每次滚动后等待2秒 for i=1,3 do splash:evaljs("window.scrollTo(0, document.body.scrollHeight)") splash:wait(2) end return splash:html() end

5.3 禁用图片加载:提升爬取速度

如果不需要页面截图,禁用图片、CSS 等资源的加载,可以大幅提升 Splash 的渲染速度:

lua

function main(splash, args) splash.images_enabled = false -- 禁用图片加载 splash:go(args.url) splash:wait(3) return splash:html() end

六、常见问题与解决方案

  1. Splash 服务连接失败

    • 检查 Docker 容器是否正常运行:docker ps
    • 确认SPLASH_URL配置正确,防火墙未拦截 8050 端口。
  2. 渲染后的页面仍无目标数据

    • 延长等待时间或使用wait_for_element等待关键元素;
    • 检查目标网站是否有反爬机制,可通过splash:set_user_agent()设置浏览器 UA。
  3. 爬虫效率过低

    • 禁用图片、CSS 加载;
    • 调整 Scrapy 的并发数(CONCURRENT_REQUESTS),避免 Splash 服务过载。

七、总结

Scrapy 与 Splash 的组合,完美解决了 JavaScript 渲染页面的爬取难题。Scrapy 负责请求调度、数据解析和持久化,Splash 负责模拟浏览器渲染,两者分工明确,极大拓展了爬虫的适用场景。在实际开发中,我们需要根据目标网站的特性编写灵活的 Lua 脚本,同时优化配置和爬取策略,才能在效率和稳定性之间找到最佳平衡点。

需要注意的是,爬虫开发应遵守目标网站的robots.txt协议,避免对服务器造成过大压力,做一个合规的开发者。

http://www.jsqmd.com/news/250334/

相关文章:

  • 实战演示:用麦橘超然Flux生成赛博朋克风城市街景
  • Fun-ASR语音识别系统搭建:基于钉钉通义大模型的实操案例
  • Qwen3-14B实战教程:从零开始部署企业级智能客服系统
  • GPT-OSS-20B-WEBUI参数调优:max_tokens与temperature设置建议
  • 5个必备翻译工具推荐:HY-MT1.5-1.8B镜像免配置上手
  • Qwen2.5-0.5B推理费用高?本地运行降本增效实战指南
  • Supertonic极速TTS实战:为技术类乐理博文注入声音
  • 轻量翻译模型HY-MT1.5-1.8B:WMT25测试集表现分析
  • FSMN VAD API接口扩展:RESTful服务封装思路
  • 《创业之路》-859- 价值发现、价值实现、价值传递、价值回报是描述商业逻辑运行过程的动态流程,而商业模式画布是一种系统化表达商业模式的静态组成。
  • 万物识别-中文-通用领域资源配置:最低显存要求实测报告
  • cv_resnet18_ocr-detection省钱技巧:按需使用GPU降低部署成本
  • 《创业之路》-860- 价值发现 → 客户细分 + 客户关系(初期) ↓ 价值实现 → 价值主张 + 关键业务 + 核心资源 + 重要合作 ↓ 价值传递 → 渠道通路 + 客户关系(维护) ↓ 价值回
  • 通义千问2.5-7B-Instruct本地运行:Mac M1芯片适配实战
  • 亲测有效!VibeVoice-TTS网页端实现多人对话语音合成
  • DCT-Net模型训练:小样本学习的实用技巧
  • JLink驱动安装方法:新手必看的Windows入门教程
  • 从部署到推理:PaddleOCR-VL-WEB实现本地图片与PDF精准识别
  • Qwen新手教程:零基础云端部署,1小时1块轻松玩转
  • BGE-M3入门指南:检索模型基础概念解析
  • 学Simulink--基础微电网场景实例:基于Simulink的直流微电网母线电压稳定控制仿真
  • 打破次元壁:用DCT-Net预置镜像制作动漫风格毕业照
  • WS2812B驱动程序实现氛围灯控制的操作指南
  • 从零开始玩转语音情感识别|基于科哥开发的SenseVoice Small
  • Java毕设项目:基于Java的网上购物商城设计与实现基于SpringBoot的网上购物商城设计与实现(源码+文档,讲解、调试运行,定制等)
  • 低成本GPU部署MGeo实战:阿里开源模型让地址对齐更高效
  • HunyuanVideo-Foley动物声音:宠物、野生动物叫声匹配准确率
  • AI智能二维码工坊实战:智能家居二维码控制
  • Qwen-Image-Edit-2509学术研究指南:学生专属GPU优惠,1毛钱/分钟
  • 万物识别模型部署避坑指南,新手少走弯路