Kage: 将网站转化为无脚本的离线二进制文件

Kage 是一个旨在通过将网站克隆为无脚本、可浏览的镜像来解决“损坏”的离线保存问题的工具。与经常留下断链或依赖外部 JavaScript 的传统“另存为”功能不同,Kage 在真实的浏览器中渲染页面,对最终的 DOM 进行快照,并剥离所有 JavaScript,以确保内容在离线状态下保持功能完备且具有私密性。

核心功能:渲染与清理

Kage 通过驱动无头 Chrome 实例来捕获页面,使其呈现出与人类视觉完全一致的效果,从而创建网站的永久离线版本。该过程遵循特定的流水线:种子 URL $\rightarrow$ 无头 Chrome (渲染) $\rightarrow$ 最终 DOM (快照) $\rightarrow$ 剥离 JS (清理) $\rightarrow$ 本地化资源 (重写链接) $\rightarrow$ 磁盘。

通过剥离所有脚本,Kage 消除了追踪、网络调用以及现代单页应用中常见的“加载中”效果。最终输出由 .html 文件和一个包含本地化 CSS、图像和字体的预留 _kage 目录组成。

部署与使用选项

Kage 提供了多种安装和运行工具的方式,以满足不同的环境需求:

  • Go 安装: go install github.com/tamnd/kage/cmd/kage@latest
  • 预构建二进制文件: 提供 .deb.rpm.apk 包。
  • Docker: 一个包含 Chromium 的容器镜像 (ghcr.io/tamnd/kage),无需在本地安装 Chrome。

克隆与镜像

kage clone 命令执行一种礼貌的广度优先爬取。它尊重 robots.txt 并使用 sitemap.xml 作为种子。关键能力包括:

  • 范围控制: 使用 --scope-prefix 将爬取限制在网站的特定部分。
  • 深度与页面限制: 使用 --max-pages--max-depth 控制数据量。
  • 延迟加载支持: --scroll 标志会触发自动滚动,以捕获仅在滚动时加载的图像。
  • 幂等性: Kage 根据写入的文件对页面进行键值化,确保无论使用何种协议(HTTP 与 HTTPS),同一个页面都不会被重复获取。

提供离线内容服务

由于现代浏览器出于安全原因经常限制通过 file:// 协议加载本地文件,kage serve 会运行一个本地 HTTP 服务器,以确保链接和资源能够正确解析。

将镜像打包成便携式产物

Kage 允许用户将基于目录的镜像压缩成单个文件,以便于共享和长期存储。

ZIM 归档文件

Kage 可以将镜像打包成 ZIM 文件格式,这是一种由 Kiwix 等项目使用的开放标准,用于离线存储 Wikipedia 和 Stack Overflow。由于 ZIM 是一个文档化的标准,由 Kage 创建的文件可以在任何 ZIM 阅读器(如 Kiwix 桌面版、Android 或 iOS 应用)中打开,从而避免了供应商锁定。

自包含二进制文件

使用 --format binary 标志,Kage 会将网站归档附加到 Kage 可执行文件的副本上。这会创建一个单个二进制文件,执行时即可离线提供网站服务,无需在目标机器上的外部依赖或 ZIM 阅读器。

对于寻求更集成体验的用户,使用 webview 标签构建 Kage 可以让这些二进制文件在原生 OS 窗口中打开网站(在 macOS 上使用 WKWebView,在 Windows 上使用 WebView2,在 Linux 上使用 WebKitGTK),而不是在浏览器标签页中打开。

技术架构

Kage 是用 Go 编写的,并组织成几个专门的包:

  • clone:管理爬取前沿、渲染工作线程和恢复状态。
  • browser:处理无头 Chrome 控制和 DOM 快照。
  • sanitize:移除脚本、事件处理器和 URL。
  • asset:下载并本地化 CSS、图像和字体。
  • zim:ZIM 阅读器和写入器的纯 Go 实现。

社区洞察与替代方案

Hacker News 上的社区讨论强调了针对这种 Web 归档方法的一些替代方案和考量因素:

  • 替代工具: 用户提到了 SingleFile,这是一个强大的替代方案,它使用 base64 字符串将所有内容打包进单个 HTML 文件,以及 HTTrack,用于传统的 wiki 镜像制作。
  • 安全疑虑: 一些用户指出,在网上分享运行二进制文件存在安全风险,并且一位用户提到 Windows Security 可能会将生成的二进制文件标记为潜在不受欢迎的软件。
  • wget 的比较: 该工具本质上是 wget --mirror 的现代版本,通过先进行渲染来处理 JavaScript 密集型页面。

"那些简陋的 HTML 转储比 '完美' 的归档更有用... 十年前左右的 Feed 流往往比精心保存的(应用程序)网站更具可用性。"

这种观点强调了 Kage 的哲学:优先考虑简单的、无脚本的 HTML,而非复杂的应用程序状态保存。

Sources