kage:两行命令把任意网站变成离线应用,JS 全部剥干净

kage:两行命令把任意网站变成离线应用,JS 全部剥干净

Seven

你有没有遇到过这种情况:精心收藏了一篇技术文章,半年后再打开,页面空白、转圈永远停不下来,或者直接跳到一个改版后的 404。你当初「保存」的不过是一个 HTML 壳子,真正的内容全靠 JavaScript 从服务器实时拉取——服务器关了,你的「收藏」也跟着死了。

kage(影)用一种近乎暴力的方式解决了这个问题:它启动一个真正的 Chrome 浏览器,等页面完全渲染完毕,把用户能看到的所有内容抓下来,然后把 JavaScript 全部删除。落盘的是纯净的 HTML + 本地化的 CSS、图片、字体,零网络依赖,打开就能看。

kage 工作流程

一、kage 是什么

kage 是一个用 Go 写的命令行工具,作者 Tam Nguyen Duc,MIT 协议开源。它的工作原理很简单:

  1. 用 headless Chrome 打开目标网页
  2. 等待页面完全加载(包括 JS 动态渲染的内容)
  3. 抓取最终的 DOM 快照
  4. 删除所有 <script> 标签和 JavaScript 事件处理
  5. 把 CSS、图片、字体下载到本地,重写 URL 指向本地路径
  6. 输出一个可以完全离线浏览的文件夹

整个过程自动、递归、可断点续传。你只需要一行命令:

1
kage clone paulgraham.com

它会把 Paul Graham 的所有文章、图片、样式表全部抓下来,变成一个本地文件夹。然后:

1
2
kage serve paulgraham.com
# 浏览器打开 http://127.0.0.1:8800

就能像访问原站一样阅读,但没有任何网络请求,没有追踪器,没有广告,没有弹窗。

二、为什么不用 wget 或 SingleFile

你可能会问:wget -m 不也能镜像网站吗?SingleFile 不也能保存完整页面吗?

网页离线保存工具对比

核心区别在于对 JavaScript 的处理方式

  • wget 直接下载原始 HTML,不执行 JS。对于现代 SPA(React、Vue、Next.js)网站,wget 下载到的几乎是一个空白壳子
  • SingleFile 在浏览器里执行 JS,然后把整个页面(包括内联的 JS)压成一个 HTML 文件。保存是保存了,但那些脚本还在——打开时可能还会尝试联网
  • kage 在 headless Chrome 里完整执行 JS,拿到最终渲染结果,然后彻底剥离所有脚本。保存的是「人类看到的样子」,而不是「服务器返回的原始代码」

还有一个关键优势:kage 的 SPA 支持是原生的。因为它用的是真正的 Chrome 渲染引擎,React 的 hydration、Vue 的响应式更新、Next.js 的客户端路由——这些在 kage 眼里和普通 HTML 没有区别,渲染完就抓,抓完就删。

三、四种输出形态

kage 不只是克隆网站,它提供了四种不同的输出格式,从灵活的文件夹到一键分发的桌面应用:

四种输出形态

3.1 文件夹模式

最基础的输出。一个文件夹,里面是 HTML 文件和 _kage/ 资源目录。用 kage serve 启动本地服务器预览,链接正常跳转,和原站体验一致。

适合场景:开发者本地文档镜像、技术博客离线备份。

3.2 ZIM 归档

ZIM 是一个开放的文件格式,专门用于离线内容存储。它是 Kiwix 项目的基础——你可能知道 Kiwix,它是那个让你在没有互联网的地方也能阅读维基百科的工具。

1
2
3
kage pack paulgraham.com               # -> paulgraham.com.zim
kage open paulgraham.com.zim # kage 内置阅读器
kiwix-serve paulgraham.com.zim # 或者用 Kiwix 服务器

ZIM 文件可以在 Kiwix 的桌面应用、Android 应用、iOS 应用里直接打开。这意味着你克隆的网站可以:

  • 传到手机上,飞机上阅读
  • 放到 U 盘里,送给没有网络的同事
  • 存档十年后还能打开(开放格式,不依赖任何特定工具)

3.3 自包含二进制

最神奇的模式。--format binary 把整个网站(ZIM 归档 + kage 自身的 HTTP 服务器)合并成一个可执行文件:

1
2
kage pack paulgraham.com --format binary -o paulgraham
./paulgraham # 直接运行,打开浏览器就能看

发给任何人,他们不需要安装 kage、不需要安装任何东西,双击就能看。唯一的代价是文件会多出约 13 MiB(kage 自身的大小)。

更厉害的是跨平台编译:你在 Mac 上可以打包出 Windows 的 exe:

1
kage pack paulgraham.com --format binary --base kage-windows-amd64.exe -o paulgraham.exe

3.4 桌面应用

在二进制的基础上加 --app,kage 会把它包装成真正的桌面应用:

  • macOS:.app bundle,有图标,双击直接打开
  • Windows:.exe(GUI 子系统,没有控制台窗口)
  • Linux:AppImage

配合 webview 标签编译,甚至可以打开一个原生窗口(WKWebView / WebView2 / WebKitGTK),而不是跳转到浏览器标签页。Paul Graham 的文章,离线阅读,看起来就像一个独立的桌面应用。

四、实战:用法详解

4.1 基本克隆

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 完整克隆
kage clone https://paulgraham.com

# 限制页面数和深度
kage clone paulgraham.com --max-pages 50 --max-depth 2

# 只克隆某个子目录
kage clone go.dev --scope-prefix /doc

# 包含子域名
kage clone example.com --subdomains

# 自动滚动触发懒加载图片
kage clone example.com --scroll

# 增量更新(只重新渲染有变化的页面)
kage clone paulgraham.com --refresh

4.2 高级选项

参数 默认值 作用
-o, --out $HOME/data/kage 输出根目录
-p, --max-pages 0(无限制) 最大页面数
-d, --max-depth 0(无限制) 链接递归深度
--scope-prefix 只爬指定路径前缀
--subdomains false 包含子域名
--exclude 排除的路径前缀(可重复)
--scroll false 自动滚动触发懒加载
--workers 4 并发渲染数
--no-robots false 忽略 robots.txt

4.3 打包与分发

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 打包为 ZIM
kage pack paulgraham.com

# 打包为自包含二进制
kage pack paulgraham.com --format binary -o pg

# 打包为 macOS 桌面应用
kage pack paulgraham.com --app

# 打包为 Windows 无控制台应用
kage pack paulgraham.com --format binary --base kage-windows-gui-amd64.exe

# 打包为 Linux AppImage
kage pack paulgraham.com --app --base kage-linux-amd64

4.4 安装方式

1
2
3
4
5
6
7
8
# Go 安装
go install github.com/tamnd/kage/cmd/kage@latest

# Docker(自带 Chromium)
docker run --rm -v "$PWD/out:/out" ghcr.io/tamnd/kage clone paulgraham.com

# 预编译二进制
# 从 https://github.com/tamnd/kage/releases 下载

kage 需要 Chrome 或 Chromium 来驱动渲染。Docker 镜像自带 Chromium,本地安装需要自行准备。

五、工作原理深入

kage 的架构按职责拆分得很清晰:

1
2
3
4
5
6
7
8
9
cli/        命令行参数和 Cobra 命令树
clone/ 爬虫核心:前端队列、渲染 worker、资产 worker、续传状态
browser/ headless Chrome 控制和 DOM 快照
sanitize/ 脚本剥离(script 标签、事件处理器、javascript: URL)
asset/ CSS/图片/字体下载和本地化
urlx/ 确定性 URL 到本地路径映射
zim/ 纯 Go 实现的 ZIM 读写器
pack/ 文件夹 → ZIM/二进制的打包逻辑
viewer/ 离线展示:系统浏览器或原生窗口

几个值得注意的设计决策:

确定性路径映射:每个 URL 都通过一个确定性函数映射到本地路径。这意味着同一个页面通过 HTTP 和 HTTPS 访问、有无尾部斜杠,都会落到同一个文件,不会重复下载。

断点续传:kage 在 _kage/state.json 里维护已访问的 URL 集合。Ctrl-C 中断后重新运行,会自动跳过已下载的页面,从上次停止的地方继续。

双池并发:Chrome 标签页池负责渲染页面,独立的 HTTP 池负责下载静态资产。两个池并行工作,最大化吞吐量。

ZIM 格式:kage 用纯 Go 实现了 ZIM 的读写,不依赖 CGO。打包是确定性的——相同的镜像总是产生字节一致的文件,UUID 由内容派生而非随机生成。

六、适用场景

技术文档离线镜像:Go 标准库文档、Rust Book、Python 官方文档——开发者最常查的东西,在飞机上、高铁上、信号差的咖啡馆里都能用。

博客/文章永久存档:互联网内容是会消失的。服务器关了、域名过期了、作者删帖了——你精心收藏的链接最终都会变成 404。kage 帮你把内容「冻结」在你想要的那个时刻。

隐私阅读:kage 输出的页面不包含任何 JavaScript,意味着没有追踪器、没有广告、没有弹窗、没有 cookie 同意框。纯粹的内容。

内容分发:打包成 ZIM 或自包含二进制后,可以通过 U 盘、AirDrop、邮件等方式分发。接收者不需要互联网,不需要安装任何软件。

知识库构建:把多个相关网站克隆打包后,就是一个离线知识库。Kiwix 生态已经有成熟的工具链来管理和检索 ZIM 文件。

七、局限性

kage 不是万能的。几个需要注意的地方:

需要 Chrome/Chromium:kage 依赖 headless Chrome 来渲染页面。没有 Chrome 的环境(如某些 CI 服务器)需要用 Docker 镜像。

大型网站耗时长:对于页面数量巨大的网站(如整个 MDN 文档),首次克隆可能需要数小时。好在有断点续传和 --max-pages 限制。

登录态页面无法处理:kage 是无头浏览器,没有登录态。需要登录才能访问的内容(如付费墙后面的新闻)无法克隆。

动态实时内容不适用:股票行情、实时聊天、在线游戏这类内容本质上不适合离线保存。

二进制体积:自包含二进制有约 13 MiB 的固定开销(kage 自身),对于小网站来说,这个开销占比可能比较大。

八、与同类工具定位对比

工具 定位 适合
kage SPA 感知的全站克隆 + 多格式打包 现代网站离线存档和分发
wget 传统 HTTP 递归下载 静态站点、文件下载
SingleFile 浏览器扩展,单页保存 临时保存单篇文章
HTTrack 老牌网站镜像工具 传统 HTML 站点
Kiwix ZIM 文件阅读器和生态系统 离线内容分发和检索

kage 的独特之处在于它既是克隆工具又是打包工具——从浏览器渲染到 ZIM 归档到桌面应用,一站式完成。其他工具通常只做其中一环。

九、社区反响

kage 于 2026 年 6 月 14 日发布,在两天内就获得了 800+ GitHub Stars,并登上了 Hacker News 首页(Show HN 讨论帖)。

社区已经非常活跃:两天内发布了 v0.3.0 到 v0.3.3 四个版本,修复了 UTF-8 编码问题、Chrome 下载干扰爬取的 bug、Ctrl-C 信号处理等。外部贡献者已经开始提交翻译和功能修复的 PR。

项目地址:github.com/tamnd/kage
文档站点:kage.tamnd.com

相关链接

  • 标题: kage:两行命令把任意网站变成离线应用,JS 全部剥干净
  • 作者: Seven
  • 创建于 : 2026-06-16 16:00:00
  • 更新于 : 2026-07-14 00:18:15
  • 链接: https://blog.oneiseven.top/2026/06/16/kage-一键克隆任意网站的离线阅读神器/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论