结合Splash与Scrapy:高效爬取动态JavaScript网站

news2025/5/9 13:14:59

在当今的Web开发中,JavaScript的广泛应用使得许多网站的内容无法通过传统的请求-响应模式直接获取。为了解决这个问题,Scrapy开发者经常需要集成像Splash这样的JavaScript渲染引擎。本文将详细介绍Splash JS引擎的工作原理,并探讨如何将其与Scrapy框架无缝结合使用。

什么是Splash?

Splash是一个轻量级的浏览器服务,专门为Python爬虫设计,用于渲染JavaScript内容。它基于WebKit引擎,提供了简单的HTTP API,使开发者能够通过发送请求来获取已渲染的页面内容。

Splash的主要特点

  1. JavaScript渲染:能够执行页面中的JavaScript代码,加载动态内容
  2. HTTP API:通过简单的RESTful接口控制浏览器行为
  3. Lua脚本支持:可以使用Lua编写复杂的抓取逻辑
  4. 多进程架构:支持并行渲染请求
  5. Scrapy集成:提供官方的Scrapy-Splash插件,方便与Scrapy集成

为什么Scrapy需要Splash?

Scrapy作为强大的爬虫框架,对于静态网站有极好的处理能力,但对于动态JavaScript渲染的网站则显得力不从心。传统Scrapy只能获取初始HTML,无法处理:

  • 无限滚动内容
  • 单页应用(SPA)
  • 需要点击或交互才能显示的内容
  • 基于AJAX动态加载的数据

安装Splash

首先需要安装Splash服务。有几种方式可以选择:

Docker方式(推荐)

docker run -p 8050:8050 scrapinghub/splash

这将在本地的8050端口启动Splash服务。

手动安装

也可以从Splash官方仓库下载源码编译安装。

Scrapy集成Splash

Scrapy官方提供了scrapy-splash包来简化集成过程。

在这里插入图片描述

安装依赖

pip install scrapy-splash

配置Splash

在Scrapy项目的settings.py中添加以下配置:

# 启用Splash下载器中间件
DOWNLOADER_MIDDLEWARES = {
    'scrapy_splash.SplashCookiesMiddleware': 723,
    'scrapy_splash.SplashMiddleware': 725,
    'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware': 810,
}

# 启用Splash的DUPEFILTER_CLASS
DUPEFILTER_CLASS = 'scrapy_splash.SplashAwareDupeFilter'

# 使用Splash的HTTPCache
HTTPCACHE_STORAGE = 'scrapy_splash.SplashAwareFSCacheStorage'

# Splash服务器设置
SPLASH_URL = 'http://localhost:8050'

使用SplashRequest

在Spider中,使用SplashRequest替代普通的Request

import scrapy
from scrapy_splash import SplashRequest

class JavaScriptSpider(scrapy.Spider):
    name = 'javascript_spider'
    start_urls = ['https://example.com']

    def start_requests(self):
        for url in self.start_urls:
            yield SplashRequest(
                url,
                self.parse,
                endpoint='render.html',  # 使用Splash的渲染端点
                args={
                    'wait': 2,  # 等待2秒让JS执行
                    'timeout': 30,  # 超时设置
                    'images': 0,  # 禁用图片加载提高速度
                }
            )

    def parse(self, response):
        # 此处的response已包含渲染后的HTML
        title = response.css('title::text').get()
        yield {'title': title}

使用Lua脚本

对于更复杂的场景,可以编写Lua脚本控制Splash行为:

-- 示例Lua脚本
function main(splash, args)
    assert(splash:go(args.url))
    assert(splash:wait(2))
    return {
        html = splash:html(),
        url = splash:url(),
    }
end

在Scrapy中使用:

yield SplashRequest(
    url,
    self.parse,
    endpoint='execute',  # 使用执行Lua的端点
    args={
        'lua_source': lua_script,
        'wait': 2,
    }
)

高级技巧

  1. 处理AJAX请求

    • 使用wait参数等待特定时间
    • 或者使用execute端点编写精确等待条件
  2. 模拟用户交互

    yield SplashRequest(
        url,
        args={
            'lua_source': '''
                function main(splash, args)
                    assert(splash:go(args.url))
                    assert(splash:wait(2))
                    splash:runjs("document.querySelector('#search').value='scrapy';")
                    assert(splash:wait(1))
                    splash:mouse_click(100, 200)
                    assert(splash:wait(2))
                    return splash:html()
                end
            ''',
            'url': url,
        }
    )
    
  3. 表单提交

    yield SplashRequest(
        url,
        args={
            'lua_source': '''
                function main(splash, args)
                    assert(splash:go(args.url))
                    assert(splash:wait(2))
                    splash:send_text('username', 'myuser')
                    splash:send_text('password', 'mypassword')
                    splash:runjs("document.querySelector('#login').click();")
                    assert(splash:wait(3))
                    return splash:html()
                end
            ''',
            'url': login_url,
        }
    )
    

性能优化

  1. 启用缓存
    • 配置HTTP缓存中间件
    • 设置合理的缓存过期时间
  2. 并行请求
    • 增加Splash的并发实例(通过Docker -p参数或手动配置)
    • 在Scrapy中增加并发请求数
  3. 选择性渲染
    • 对不需要JS的页面使用普通请求
    • 通过dont_filter参数避免重复渲染

常见问题解决

  1. Splash无法加载某些页面
    • 检查是否有反爬机制(如Cloudflare)
    • 尝试设置User-Agent或使用代理
  2. 性能问题
    • 减少不必要的wait时间
    • 禁用图片加载('images': 0
    • 增加Splash的内存和CPU资源
  3. Lua脚本错误
    • 使用Splash的日志功能调试
    • 逐步测试Lua脚本的每个部分

替代方案比较

虽然Splash是一个优秀的选择,但也可以考虑其他方案:

工具优点缺点
Splash轻量级,Scrapy集成好需要额外服务
Selenium功能强大资源消耗大,速度慢
Playwright现代API,多浏览器支持设置较复杂
Puppeteer性能好,Node.js方案需要非Python环境

结论

Splash为Scrapy提供了强大的JavaScript渲染能力,使得爬取动态网站变得可行甚至简单。虽然它需要额外的服务配置,但对于需要处理现代Web应用的爬虫项目来说,这是一个值得投资的工具。通过合理配置和优化,可以构建高效、稳定的动态网站爬虫系统。

对于需要处理大量动态内容的爬虫项目,建议采用Splash与Scrapy的组合方案,并根据具体需求调整Lua脚本和请求参数。随着Web技术的发展,掌握这样的动态爬取技术将成为爬虫工程师的重要技能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2371488.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

用于构建安全AI代理的开源防护系统

大家读完觉得有帮助记得及时关注!!! 大型语言模型(LLMs)已经从简单的聊天机器人演变为能够执行复杂任务的自主代理,例如编辑生产代码、编排工作流程以及基于不受信任的输入(如网页和电子邮件&am…

克里金模型+多目标优化+多属性决策!Kriging+NSGAII+熵权TOPSIS!

目录 效果一览基本介绍程序设计参考资料 效果一览 基本介绍 克里金模型多目标优化多属性决策!KrigingNSGAII熵权TOPSIS!!matlab2023b语言运行! 1.克里金模型(Kriging Model)是一种基于空间统计学的插值方法…

LLM 论文精读(三)Demystifying Long Chain-of-Thought Reasoning in LLMs

这是一篇2025年发表在arxiv中的LLM领域论文,主要描述了长思维链 Long Chain-of-Thought 对LLM的影响,以及其可能的生成机制。通过大量的消融实验证明了以下几点: 与shot CoT 相比,long CoT 的 SFT 可以扩展到更高的性能上限&…

【Prompt工程—文生图】案例大全

目录 一、人物绘图 二、卡通头像 三、风景图 四、logo设计图 五、动物形象图 六、室内设计图 七、动漫风格 八、二次元图 九、日常场景图 十、古风神化图 十一、游戏场景图 十二、电影大片质感 本文主要介绍了12种不同类型的文生图技巧,通过加入不同的图像…

rust程序静态编译的两种方法总结

1. 概述 经过我的探索,总结了两种rust程序静态编译的方法,理论上两种方法都适用于windows、mac os和linux(mac os未验证),实测方法一性能比方法二好,现总结如下,希望能够帮到你. 2.方法一 2.1 添加配置文件 在项目的同级文件夹下新…

【Linux系列】目录大小查看

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

2048游戏(含Python源码)

前言 相关参考游戏: 像素飞机大战(含Python源码)-CSDN博客https://blog.csdn.net/weixin_64066303/article/details/147693018?spm1001.2014.3001.5501使用DeepSeek定制Python小游戏——以“俄罗斯方块”为例-CSDN博客https://blog.csdn.n…

中间件-RocketMQ

RocketMQ 基本架构消息模型消费者消费消息模式顺序消息机制延迟消息批量消息事务消息消息重试最佳实践 基本架构 nameServer: 维护broker列表信息,客户端连接时只需要连接nameServer。可配置成集群。 broker:broker分为master和slave,master负…

Python就业方向有哪些?

Python 作为一门通用、易学且功能强大的编程语言,在多个领域都有广泛的应用,因此就业方向也非常多样化。以下是 Python 主要的就业方向及相关技能要求。 1. Web 开发 岗位:Python Web 开发工程师、后端工程师、全栈工程师技术栈&#xff1a…

iptables 访问控制列表使用记录

iptables 是linux操作系统上自带的防火墙程序,功能强大,能够依据策略过滤掉一些恶意访问流量,本次记录一下iptables的常见使用方法,未尽之处,欢迎补充。 一、iptables 下载 我这里使用的是华为openEuler 22.03版本&am…

16. Qt系统相关:事件、定时器

1. Qt事件 1.1 简介 事件是应用程序内部或者外部产生的事情或者动作的统称。在Qt中使用一个对象来表示一个事件。所有的Qt事件均继承于抽象类QEvent。事件是由系统或者Qt平台本身在不同的时刻发出的。当用户按下鼠标、敲下键盘,或者是窗口需要重新绘制的时候&#…

云平台搭建

物联网云平台的基本概述 基本概念 随着物联网技术的快速发展,越来越多的设备需要接入网络以实现智能化功能,物联网平台应运而生。 物联网云平台(IoT Cloud Platform)是物联网生态系统中的核心组件,它通过提供一系列…

数学实验(Matlab语言环境和线性代数实验)

一、Matlab语言环境和线性代数实验 1.Matlab语言环境 Matlab简介 Matlab:Matrix Laboratry 矩阵实验室 Matlab 提供了强大的科学计算、灵活的程序设计流程、高质量的图形可视化与界面设计等功能,被广泛应用于科学计算、控制系统、信息处理等领域的分…

Elasticsearch 中的索引模板:如何使用可组合模板

作者:来自 Elastic Kofi Bartlett 探索可组合模板以及如何创建它们。 更多阅读: Elasticsearch:可组合的 Index templates - 7.8 版本之后 想获得 Elastic 认证吗?查看下一期 Elasticsearch Engineer 培训的时间! El…

【LeetCode 42】接雨水(单调栈、DP、双指针)

题面: 思路: 能接雨水的点,必然是比两边都低(小)的点。有两种思路,一种是直接计算每个点的最大贡献(也就是每个点在纵向上最多能接多少水),另一种就是计算每个点在横向上…

【JS逆向基础】前端基础-HTML与CSS

1,flask框架 以下是一个使用flask框架写成的serve程序 # noinspection PyUnresolvedReferences #Flash框架的基本内容from flask import Flask app Flask(__name__)app.route(/index) def index():return "hello index"app.route(/login) def login():re…

手机网页提示ip被拉黑名单什么意思?怎么办

‌当您使用手机浏览网页时,突然看到“您的IP地址已被列入黑名单”的提示,是否感到困惑和不安?这种情况在现代网络生活中并不罕见,但确实会给用户带来诸多不便。本文将详细解释IP被拉黑的含义、常见原因,并提供一系列实…

CCF编程能力等级认证 一级 第一次课

介绍 CCF 编程能力等级认证(GESP)为青少年计算机和编程学习者提供学业能力验证的规则和平台,由中国计算机学会发起并主办。 每年考试分四次,时间是每年的3月、6月、9月、12月,以当年每期公布的时间为准。 GESP适用年…

SpringBoot 讯飞星火AI WebFlux流式接口返回 异步返回 对接AI大模型 人工智能接口返回

介绍 用于构建基于 WebFlux 的响应式 Web 应用程序。集成了 Spring WebFlux 模块,支持响应式编程模型,构建非阻塞、异步的 Web 应用。WebFlux 使用了非阻塞的异步模型,能够更好地处理高并发请求。适合需要实时数据推送的应用场景。 WebClie…

Python爬虫中time.sleep()与动态加载的配合使用

一、动态加载网页的挑战 动态加载网页是指网页的内容并非一次性加载完成,而是通过JavaScript等技术在用户交互或页面加载过程中逐步加载。这种设计虽然提升了用户体验,但对于爬虫来说,却增加了抓取的难度。传统的爬虫方法,如简单…