ブラウザーで表示しているWebサイトを保存しても、JavaScriptによるデータ取得や外部サービスとの通信に依存している場合、オフライン環境では本文が表示されなかったり、画像やレイアウトが崩れたりすることがあります。「kage」はChromeでページの表示を完成させた後にJavaScriptを取り除き、HTMLや画像などをまとめてローカルへ保存することで、動的に生成された内容をオフラインでも確認できるツールです。

kage

https://kage.tamnd.com/



tamnd/kage: Shadow any website for offline viewing, with the JavaScript stripped out

https://github.com/tamnd/kage

◆kageの基本機能

Windows・MacOS・Linux対応のコマンドラインツールで、指定したサイトのrobots.txtやsitemap.xmlを自動的に解析し、サイト全体を階層的に巡回し保存します。

◆kageの特長

・ブラウザ駆動による確実なスナップショット

単にHTMLソースをダウンロードするのではなく、内部でヘッドレスChromeを実際に動かしてページを完全にレンダリングし、JavaScriptによって動的に生成されるコンテンツや遅延読み込みされる画像を、実際にサイトを閲覧した状態でキャプチャします。

・スクリプトの削除

キャプチャ後、ブラウザからDOMデータを取得しJavaScriptタグやクリックイベントなどのイベントハンドラを完全に除去することによって、外部サーバーへの通信が一切発生しない静的なHTMLファイルへと変換されます。

・単一バイナリ・アプリ化機能

クローンしたフォルダーをそのまま保存するだけでなく、Wikipediaのコンテンツに使用されるオープン規格の圧縮アーカイブ「ZIM形式」への変換やWebサイト自体をダブルクリックで独立したウィンドウが開く「デスクトップアプリ」としてパッケージングできます。

◆その他の機能一覧

・レジューム機能:クロール中にCtrl+Cで中断しても進捗が自動保存されているため、次回実行時に続きから再開できます。

・差分更新:すでにクローン済みのデータを飛ばして、新しく追加されたページだけを再レンダリングして更新。

・ローカルプレビュー用サーバー:HTTPサーバー機能により、ローカル環境で実サイト同様の挙動をプレビュー可能。

◆kageの使い方

今回はWindowsにDocker DesktopとGit for WindowsのGit Bashを用意した環境で作業します。

・サイトの取得

例えば「GIGAZINE.BIZ」を取得する場合、「kage clone gigazine.biz」というコマンドに「最大50ページまで」「リンクは1階層まで」「サイトマップは利用しない」とオプション指定することでホームページからリンクされている1階層分のページを取得します。


MSYS_NO_PATHCONV=1 docker run --rm -v "./out:/out" \
ghcr.io/tamnd/kage clone gigazine.biz \
--max-pages 50 --max-depth 1 --no-sitemap


以下のような実行結果になりました。


kage cloning https://gigazine.biz/
kage: container detected, Chrome sandbox disabled
done /out/data/kage/gigazine.biz
pages 15 assets 40
open kage serve /out/data/kage/gigazine.biz


・取得したサイトの閲覧

実行結果に表示されるコマンド「open kage serve /out/data/kage/gigazine.biz」をDockerコマンドに変換して実行。


MSYS_NO_PATHCONV=1 docker run --rm -p 8800:8800 \
-v "./out:/out" ghcr.io/tamnd/kage serve \
/out/data/kage/gigazine.biz -a 0.0.0.0:8800


サーバーが起動し「http://[::]:8800」と表示されたらブラウザを起動し「http://127.0.0.1:8800」にアクセスすると…


kage serve /out/data/kage/gigazine.biz
open http://[::]:8800
press Ctrl-C to stop


GIGAZINE.BIZのトップページが表示されました。「そもそも記事広告って何?」のリンクをクリック。



「http://127.0.0.1:8800/what-is-advertorial/」でアクセスされており、子ページへのアクセスもローカルで正常に行われていました。



・ZIMファイルとして一元化

サイトを取得した後、「kage pack」コマンドを実行するとoutフォルダー内に「gigazine.biz.zim」というZIMファイルが作成されます。


MSYS_NO_PATHCONV=1 docker run --rm -v "./out:/out" \
ghcr.io/tamnd/kage pack gigazine.biz


ZIMファイルの閲覧は「kage open」コマンドでserveと同様のサーバーが立ち上がります。


MSYS_NO_PATHCONV=1 docker run --rm -p 8800:8800 \
-v "./out:/out" ghcr.io/tamnd/kage open \
/out/gigazine.biz.zim -a 0.0.0.0:8800


・サイトのアプリ化

Releases · tamnd/kage

https://github.com/tamnd/kage/releases

土台となるexeファイルが必要なためリポジトリのReleasesページにアクセスし「kage_0.3.10_windows-gui_amd64.zip」をクリックし保存。



ZIPファイルを展開し「kage.exe」ファイルをoutフォルダーにコピーしたら準備完了。



アプリ化するため「kage pack」コマンドにオプションで「--format binary --base ./out/kage.exe」を指定し実行。


MSYS_NO_PATHCONV=1 docker run --rm -v "./out:/out" \
ghcr.io/tamnd/kage pack gigazine.biz \
--format binary --base /out/kage.exe


実行結果は以下の通り。「gigazine.exe」がoutフォルダーに作成されています。


packed gigazine.exe
size 24.4 MiB
this is a Windows viewer; copy gigazine.exe to that machine to run it


gigazine.exeを実行。


./out/gigazine.exe


ブラウザが起動し保存したサイトが表示されます。



ソーシャル系ニュースサイトのHacker Newsでは、kageについてさまざまな議論が行われており、SingleFileと比較して「SingleFileではJavaScriptだけでなくWebフォントや画像などをbase64文字列に変換し全てのアセットを1つのHTMLとしてパックします。」という指摘がありました。これに対して作者は「SingleFileが主に1ページを保存するのに対し、kageはサイト内の複数ページを巡回してページ間を移動できる状態でサイト全体を保存することを目的としている」と説明しています。なお、SingleFileから派生したSingleFile CLI版ではサイト全体のクロールに対応しています。