Splash:Scrapinghub 开源的 JavaScript 渲染服务|Docker 部署与 HTTP API 全指南
Splash 是一个带 HTTP API 的轻量级浏览器渲染服务,用 Python 3 + Twisted + Qt5 实现,无状态、易分布式部署。本文按官方 README 与文档站,梳理 Docker 一键启动、默认端口 8050、
render.html/render.png/execute端点、Lua 脚本接口与 Scrapy 集成。
1. 项目简介与定位
Splash 是一个 JavaScript 渲染服务,对外暴露 HTTP API。它本质上是一个带 HTTP 接口的轻量级浏览器,用 Python 3 实现,基于 Twisted 与 Qt5(QtWebKit)。它的特点是快、轻量、无状态——这让它非常容易在多台机器上水平分发。
Splash 适合:你不想在每个抓取脚本里都内嵌一个完整浏览器,而是想把"渲染 JS、等页面加载、截图、抓 HAR"这一类需求集中到一个自托管的 HTTP 服务上,让上游的 Scrapy / requests / Go 程序通过 URL 参数调用它。
1.1 核心信息一览
| 项 | 内容 |
|---|---|
| 项目名 | Splash |
| 仓库 | https://github.com/scrapinghub/splash |
| 文档站 | https://splash.readthedocs.io/ |
| 出品方 | Scrapinghub(现 Zyte) |
| 主语言 | Python 3 / Twisted / Qt5(QtWebKit) |
| 部署形态 | Docker 镜像 scrapinghub/splash |
| 默认端口 | 8050(HTTP) |
| 许可证 | BSD 3-Clause |
| 脚本接口 | Lua(在页面上下文里执行自定义逻辑) |
1.2 适用场景
- 给 Scrapy 爬虫提供 JS 渲染能力(配合
scrapy-splash) - 输入一个 URL,直接拿到渲染后的 HTML / PNG / JPEG / HAR
- 用 Lua 脚本编排:等某个元素出现、滚动页面、点按钮、抽数据
- 作为内网渲染服务,被多个抓取 / 监控 / 截图程序共享
1.3 能力边界(官方口径)
Splash 用的是 QtWebKit,不是完整的 Chrome / Chromium。它能跑绝大多数传统 JS 站点,但对非常新的 Web API、ES2022+、复杂 SPA 框架(重度依赖最新 V8)可能渲染不全。需要完整 Chrome 行为时,请改用 Playwright / Puppeteer 自托管服务。Splash 官方 README 也提示:商业支持由 Scrapinghub 提供。
2. 开源协议
Splash 采用 BSD 3-Clause License。详见 https://github.com/scrapinghub/splash/blob/master/LICENSE 。
3. 官方仓库链接
- 仓库:https://github.com/scrapinghub/splash
- 文档站:https://splash.readthedocs.io/
- HTTP API 文档:https://splash.readthedocs.io/en/stable/api.html
- Lua 脚本教程:https://splash.readthedocs.io/en/stable/scripting-tutorial.html
- Lua API 参考:https://splash.readthedocs.io/en/stable/scripting-ref.html
- Scrapy 集成库:https://github.com/scrapy-plugins/scrapy-splash
- Issues(开源支持):https://github.com/scrapinghub/splash/issues
- 商业支持:https://scrapinghub.com
4. 前置要求
| 依赖 | 版本要求 | 说明 |
|---|---|---|
| Docker | 17 或更新 | 官方文档明确要求 |
| 操作系统 | Linux / macOS(Docker Desktop) | Windows 走 Docker Desktop |
| 端口 | 8050(默认) | 宿主机需可访问;生产建议只对内网开放 |
| 内存 | 建议 1 GB+ | 每个并发渲染页面都会占用 QtWebKit 渲染进程 |
| 网络 | 可访问目标站点 | Splash 服务器需能直连被抓取 URL |
不要把 Splash 直接暴露到公网——它没有身份认证,任何人都能用它渲染任意 URL,会被当作开放代理滥用。生产环境务必放在内网,或在前面加反向代理 + Basic Auth / IP 白名单。
5. 安装部署(Docker 一键启动)
下面的命令来自官方安装文档(https://splash.readthedocs.io/en/stable/install.html )。
5.1 拉取镜像
docker pull scrapinghub/splash5.2 启动容器
docker run -it -p 8050:8050 --rm scrapinghub/splash启动后 Splash 监听 0.0.0.0:8050(HTTP)。本机访问
http://localhost:8050/ 会看到一个 Web
调试界面,可以在里面直接输入 URL 测试渲染。
5.3 后台常驻 + 资源限制
docker run -d --name splash \
-p 127.0.0.1:8050:8050 \
--restart=unless-stopped \
--memory=2g --cpus=2 \
scrapinghub/splash \
--max-timeout=60 --disable-lua-sandbox常用启动参数(来自官方文档 "Passing Custom Options"):
| 参数 | 作用 |
|---|---|
-p 8050:8050 |
映射 HTTP 端口 |
--max-timeout=N |
单页最大渲染秒数(默认 30,可调大到 60) |
--disable-lua-sandbox |
关闭 Lua 沙箱,允许更全的系统能力 |
--proxy PROXY_URL |
全局出站代理 |
-v /path/to/profiles:/etc/splash/proxy-profiles |
挂载代理配置目录 |
-v /path/to/filters:/etc/splash/request-filter-profiles |
挂载请求过滤器 |
5.4 自建镜像(可选)
git clone https://github.com/scrapinghub/splash.git
cd splash
docker build -t my-local-splash .
# 带 Jupyter 的实验镜像
docker build -t my-local-splash-jupyter -f dockerfiles/splash-jupyter/Dockerfile .6. 最小示例:HTTP API 调用
Splash 的核心端点如下(来自官方 HTTP API 文档目录):
| 端点 | 返回 | 用途 |
|---|---|---|
GET /render.html |
HTML 文本 | 渲染后页面的源代码 |
GET /render.png |
PNG 图片 | 整页截图 |
GET /render.jpeg |
JPEG 图片 | 整页截图(更小体积) |
GET /render.har |
HAR JSON | 网络请求日志 |
GET /render.json |
JSON | 同时返回 HTML / 截图 / HAR / 自定义 JS 结果 |
POST /execute |
JSON | 运行自定义 Lua 脚本 |
GET /run |
视 Lua 返回值 | 运行 Lua 脚本(GET 形式) |
GET /_ping |
ok + 内存 |
健康检查 |
GET /_debug |
JSON | 当前请求、队列、对象统计 |
POST /_gc |
— | 手动触发垃圾回收 |
6.1 渲染并取 HTML
curl 'http://localhost:8050/render.html?url=https://example.com&wait=2'url:目标 URL(必填)wait:渲染后额外等待多少秒,让setTimeout/setInterval回调有机会执行。官方文档提示:如果页面里有定时器,wait=0时这些回调不会跑;做 PNG / JPEG 全页截图时也需要非零wait。proxy:代理 profile 名或[user:pass@]host:port形式的代理 URL。
6.2 截图
# 整页 PNG
curl 'http://localhost:8050/render.png?url=https://example.com&wait=2&width=1280&height=800' -o shot.png
# JPEG
curl 'http://localhost:8050/render.jpeg?url=https://example.com&wait=2&quality=80' -o shot.jpg6.3 一次拿多种结果(render.json)
curl 'http://localhost:8050/render.json?url=https://example.com&wait=2&html=1&png=1&har=1'6.4 健康检查
curl http://localhost:8050/_ping
# {"status": "ok", "maxrss": ...}7. Lua 脚本接口(execute)
/execute 是 Splash 最强大的端点:你写一段 Lua,Splash
在页面上下文里按你的编排执行。下面这段官方常见模式:打开页面、等某个选择器出现、读文本、返回
JSON。
function main(splash, args)
splash:set_user_agent('Mozilla/5.0 (compatible; MyBot/1.0)')
splash:autoclose_onerror(false)
assert(splash:go(args.url))
splash:wait(2.0)
-- 滚动到底部触发懒加载
splash:evaljs("window.scrollTo(0, document.body.scrollHeight)")
splash:wait(1.0)
local title = splash:evaljs("document.title")
local items = splash:evaljs([[
Array.from(document.querySelectorAll('a.item')).map(a => a.href)
]])
return {
title = title,
links = items,
html = splash:html(),
png = splash:png{width=1280, height=800},
}
end调用方式(POST,lua_source 字段传脚本):
curl 'http://localhost:8050/execute' \
-F 'url=https://example.com' \
-F 'lua_source=@myscript.lua'Lua API 完整参考见 https://splash.readthedocs.io/en/stable/scripting-ref.html
。常用对象:splash(浏览器)、args(URL
参数)、request /
response、element、cookies_enabled、resource_timeout、images_enabled
等。
8. 配置项
| 配置 | 作用 | 默认 |
|---|---|---|
| 默认监听端口 | HTTP 服务端口 | 8050 |
--max-timeout |
单请求最大秒数 | 30 |
--timeout |
默认超时 | 由 --max-timeout 约束 |
--wait(请求参数) |
渲染后额外等待秒 | 0 |
--proxy(启动参数) |
全局出站代理 | 无 |
proxy(请求参数) |
单请求代理 profile 或 URL | 无 |
resource_timeout(Lua) |
单个资源加载超时 | 无 |
images_enabled(Lua) |
是否加载图片(关掉可加速) | 开 |
http_method(请求参数) |
出站 GET 或 POST | GET |
save_args |
把长参数缓存起来,后续请求用 SHA1 引用 | 无 |
/etc/splash/proxy-profiles/ |
代理 profile 配置目录 | 容器内默认存在 |
/etc/splash/request-filter-profiles/ |
请求过滤器目录 | 容器内默认存在 |
9. 与 Scrapy 集成
官方 README 直接指向 scrapy-splash。在
Scrapy `settings.py` 里:
SPLASH_URL = 'http://localhost:8050'
DOWNLOADER_MIDDLEWARES = {
'scrapy_splash.SplashCookiesMiddleware': 723,
'scrapy_splash.SplashMiddleware': 725,
'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware': 810,
}
SPIDER_MIDDLEWARES = {
'scrapy_splash.SplashDeduplicateArgsMiddleware': 100,
}
DUPEFILTER_CLASS = 'scrapy_splash.SplashAwareDupeFilter'在 spider 里用 SplashRequest 代替
scrapy.Request:
from scrapy_splash import SplashRequest
class MySpider(scrapy.Spider):
def start_requests(self):
yield SplashRequest(
url='https://example.com',
callback=self.parse,
args={'wait': 2, 'html': 1},
)10. 常见问题
Q1:启动后访问 8050 打不开? A:确认
docker ps 里容器在跑、端口映射是
0.0.0.0:8050->8050/tcp;云服务器安全组 / 防火墙要放行
8050(或建议只绑 127.0.0.1,再用 Nginx 加 Basic
Auth)。
Q2:渲染出来的 HTML 里没有我要的内容? A:加大
wait=,或在 Lua 里
splash:wait_for_element('#foo');也可能是站点用了 QtWebKit
不支持的新 Web API,这种情况请改用 Playwright / Chromium 类服务。
Q3:内存越用越大? A:Splash 文档提供
POST /_gc 手动回收;长期跑建议配 --max-timeout
限制单页渲染时间、挂 --memory
限制容器内存,必要时定时重启容器。
Q4:怎么加代理? A:启动时
--proxy http://host:port 全局加;或在
/etc/splash/proxy-profiles/ 下放 *.ini
定义命名 profile,请求时 ?proxy=myprofile。
Q5:能不能关掉图片加载加速? A:Lua 脚本里
splash.images_enabled = false,整页就不会加载图片,渲染速度明显提升。
Q6:Splash 与 Playwright / Puppeteer 自托管怎么选? A:Splash 轻、无状态、HTTP + Lua 接口简单,适合传统站点和 Scrapy 流水线;Playwright / Puppeteer 基于完整 Chromium,能跑现代 SPA,但资源占用大、需要自己写服务封装。
11. 与同类工具对比
| 维度 | Splash | Playwright 自托管 | Puppeteer + Express | Selenium Grid |
|---|---|---|---|---|
| 浏览器内核 | QtWebKit | 完整 Chromium / Firefox / WebKit | Chromium | 各浏览器 driver |
| 接口 | HTTP + Lua | 语言 SDK(需自己包 HTTP) | 自己写 HTTP | W3C WebDriver 协议 |
| 资源占用 | 小 | 大 | 中 | 中 |
| 无状态 / 易横向扩 | 是 | 需自己做 | 需自己做 | 是(Grid) |
| 现代 SPA 支持 | 弱 | 强 | 强 | 强 |
| 默认端口 | 8050 | 自定义 | 自定义 | 4444 |
12. 许可
BSD 3-Clause。详见 https://github.com/scrapinghub/splash/blob/master/LICENSE 。商业支持由 Scrapinghub(Zyte)提供。
13. 责任使用声明
使用 Splash 渲染或抓取任何站点时,请遵守目标站点的
robots.txt
与服务条款(ToS)。请合理控制并发数与请求频率,在请求之间加入延时,避免对目标服务器造成压力。请勿用
Splash
绕过登录验证、付费墙、验证码或反爬系统。请勿批量抓取、存储或传播个人隐私数据。本工具仅应用于公开数据的合法研究、自身业务的页面渲染与截图、授权范围内的自动化任务。请尊重网页内容的版权,二次发布抓取结果需获得权利人许可。