aboutsummaryrefslogtreecommitdiffhomepage
path: root/services
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2025-12-06 20:52:52 +0900
committernsfisis <nsfisis@gmail.com>2025-12-06 20:52:52 +0900
commit3e9c900e00b17b4e31f5e9476216d76b75342443 (patch)
tree273e20e0d87479e4c510e7e3341c7f2f93e23540 /services
parent3704a9bf7eea6d7bef67eba6d2ef10be4ae5c24c (diff)
downloadnsfisis.dev-3e9c900e00b17b4e31f5e9476216d76b75342443.tar.gz
nsfisis.dev-3e9c900e00b17b4e31f5e9476216d76b75342443.tar.zst
nsfisis.dev-3e9c900e00b17b4e31f5e9476216d76b75342443.zip
feat(blog): new post /posts/2025-12-06/archive-dynamic-site-with-wget/
Diffstat (limited to 'services')
-rw-r--r--services/nuldoc/content/posts/2025-12-06/archive-dynamic-site-with-wget.md100
-rw-r--r--services/nuldoc/nuldoc-src/commands/new.ts5
-rw-r--r--services/nuldoc/public/blog/posts/2/index.html46
-rw-r--r--services/nuldoc/public/blog/posts/2025-12-06/archive-dynamic-site-with-wget.md100
-rw-r--r--services/nuldoc/public/blog/posts/2025-12-06/archive-dynamic-site-with-wget/index.html178
-rw-r--r--services/nuldoc/public/blog/posts/3/index.html41
-rw-r--r--services/nuldoc/public/blog/posts/4/index.html35
-rw-r--r--services/nuldoc/public/blog/posts/5/index.html40
-rw-r--r--services/nuldoc/public/blog/posts/6/index.html20
-rw-r--r--services/nuldoc/public/blog/posts/atom.xml10
-rw-r--r--services/nuldoc/public/blog/posts/index.html35
11 files changed, 505 insertions, 105 deletions
diff --git a/services/nuldoc/content/posts/2025-12-06/archive-dynamic-site-with-wget.md b/services/nuldoc/content/posts/2025-12-06/archive-dynamic-site-with-wget.md
new file mode 100644
index 0000000..164d52f
--- /dev/null
+++ b/services/nuldoc/content/posts/2025-12-06/archive-dynamic-site-with-wget.md
@@ -0,0 +1,100 @@
+---
+[article]
+uuid = "02f33085-d81e-4b94-b247-e120ec6e809c"
+title = "wget を使って動的サイトを静的サイトにアーカイブする"
+description = "運用停止した動的サイトを wget でクロールし、静的ファイルのみで配信できるようにした。"
+tags = [
+]
+
+[[article.revisions]]
+date = "2025-12-06"
+remark = "公開"
+---
+# はじめに {#intro}
+
+2024 年に開催された [PHPerKaigi 2024](https://phperkaigi.jp/2024/) において、コードゴルフ企画が開催された。
+私はシステムの開発と当日の運用を担当し、 https://t.nil.ninja/phperkaigi/2024/golf/ でサイトを公開した。
+
+カンファレンスの終了に伴ってこちらのサイトも新規の回答は締め切ったが、以前としてシステムは動的なサイトとして動いていた。
+
+サーバのリソースがもったいないので、このたび wget コマンドを用いてアーカイブし、静的なファイルを Nginx で配信するだけの構成とした。
+
+
+# アーカイブする {#archive}
+
+* 元々の動的サイトに対応するリポジトリはこちら: https://github.com/nsfisis/phperkaigi-2024-albatross
+* 移行後の静的サイトに対応するリポジトリはこちら: https://github.com/nsfisis/phperkaigi-2024-albatross-archive
+
+元々の動的サイトは PHP で構築されたウェブサイト部分と、投稿されたゴルフの回答を実行してテストするサンドボックス環境部分に分かれていた。
+
+新規の投稿を締め切った今、必要なのは問題文や結果を表示する HTML とそれに付随する JavaScript、CSS、画像などの静的ファイルのみである。
+
+wget コマンドを使うと、必要な静的ファイルを集める作業をほとんどすべて自動でおこなうことができる。
+
+今回使用したスクリプトはこちら:
+https://github.com/nsfisis/phperkaigi-2024-albatross-archive/blob/cc837f6d2109555e2392016e8f6820fb5fd46dd6/archive.sh
+
+```bash
+# 指定した URL からスタートしてリンクを辿りながら全ファイルをファイルに書き出す
+#
+# --mirror リンクを再帰的に辿ってダウンロードする
+# --page-requisites CSS や画像等も含めて HTML から参照されている全ファイルをダウンロードする
+# --convert-links リンクを相対リンクへ変換する
+# --adjust-extension URL に拡張子が無くてもいい感じに推測する
+# --no-parent 親ディレクトリは見に行かない
+# --no-wait=1 リクエスト間で 1 秒待機する
+# -P ./archive/ 指定したディレクトリに保存する
+wget \
+ --mirror \
+ --page-requisites \
+ --convert-links \
+ --adjust-extension \
+ --no-parent \
+ --wait=1 \
+ -P ./archive/ \
+ https://t.nil.ninja/phperkaigi/2024/golf/
+
+# ディレクトリ構造を調整する
+mv ./archive/t.nil.ninja/phperkaigi/2024/golf/* ./archive
+rmdir ./archive/t.nil.ninja/phperkaigi/2024/golf/
+rmdir ./archive/t.nil.ninja/phperkaigi/2024/
+rmdir ./archive/t.nil.ninja/phperkaigi/
+rmdir ./archive/t.nil.ninja/
+
+mkdir -p ./archive/api/quizzes/{1,2,3}
+
+# 動的な API エンドポイントを叩いて結果を JSON ファイルとして保存する
+wget -O ./archive/api/quizzes/1/chart.json https://t.nil.ninja/phperkaigi/2024/golf/api/quizzes/1/chart
+wget -O ./archive/api/quizzes/2/chart.json https://t.nil.ninja/phperkaigi/2024/golf/api/quizzes/2/chart
+wget -O ./archive/api/quizzes/3/chart.json https://t.nil.ninja/phperkaigi/2024/golf/api/quizzes/3/chart
+
+# 上記 API を叩いている箇所を、落としてきた静的ファイルを参照するように変更する
+sed -i -e 's#/chart`#/chart.json`#' ./archive/assets/chart.js
+```
+
+このように wget に適切なオプションを渡すことで、指定したページから遷移可能なページを再帰的に辿っていき、サイト内の全ページをファイルへ落とすことができる。
+今回のサイトにはページ遷移では辿り着けないページがあったが (管理画面など)、運用が停止している今そういったページはアーカイブしなくてもよい。
+
+あとはこのファイルを適当にサーブしてやればよい。
+
+```nginx
+server {
+ listen 80 default;
+ listen [::]:80;
+
+ charset UTF-8;
+
+ location /phperkaigi/2024/golf/ {
+ alias /archive/;
+ }
+}
+```
+
+
+# おわりに {#outro}
+
+当初はリンクを再帰的に辿るようなスクリプトを手で書いていたのだが、wget を使うことではるかに簡単な手順でサイト全体のアーカイブが実施できた。
+
+JavaScript から動的にバックエンドの Web API を叩いている箇所については wget だけだと難しいので、複雑なサイトの場合はここが課題となるだろう。
+
+カンファレンスの企画用に作成した運用停止済みのシステムは他にもあるので、それらも順次アーカイブ化を進めていこうと思う。
diff --git a/services/nuldoc/nuldoc-src/commands/new.ts b/services/nuldoc/nuldoc-src/commands/new.ts
index 651c59e..f355376 100644
--- a/services/nuldoc/nuldoc-src/commands/new.ts
+++ b/services/nuldoc/nuldoc-src/commands/new.ts
@@ -50,7 +50,7 @@ OPTIONS:
}
function getFilename(type: "post" | "slide"): string {
- return type === "post" ? "TODO.dj" : "TODO.toml";
+ return type === "post" ? "TODO.md" : "TODO.toml";
}
function getDirPath(type: "post" | "slide"): string {
@@ -73,8 +73,7 @@ tags = [
date = "${date}"
remark = "公開"
---
-{#TODO}
-# TODO
+# はじめに {#intro}
TODO
`;
diff --git a/services/nuldoc/public/blog/posts/2/index.html b/services/nuldoc/public/blog/posts/2/index.html
index 1e3476d..5c6e5b4 100644
--- a/services/nuldoc/public/blog/posts/2/index.html
+++ b/services/nuldoc/public/blog/posts/2/index.html
@@ -67,6 +67,26 @@
</div>
</nav>
<article class="post-entry">
+ <a href="/posts/2025-03-27/zip-function-like-command-paste-command/">
+ <header class="entry-header">
+ <h2>zip 関数のようなコマンド paste</h2>
+ </header>
+ <section class="entry-content">
+ <p>
+ zip 関数のような動きをする paste コマンドについてのメモ。
+ </p>
+ </section>
+ <footer class="entry-footer">
+ <time datetime="2025-03-27">2025-03-27</time> 投稿
+ <ul class="entry-tags">
+ <li class="tag">
+ <span class="tag-inner">備忘録</span>
+ </li>
+ </ul>
+ </footer>
+ </a>
+ </article>
+ <article class="post-entry">
<a href="/posts/2025-02-24/phpcon-nagoya-2025-report/">
<header class="entry-header">
<h2>PHP カンファレンス名古屋 2025 参加レポ</h2>
@@ -271,32 +291,6 @@
</footer>
</a>
</article>
- <article class="post-entry">
- <a href="/posts/2024-05-11/phpconkagawa-2024-report/">
- <header class="entry-header">
- <h2>PHP カンファレンス香川 2024 参加レポ</h2>
- </header>
- <section class="entry-content">
- <p>
- 2024-05-11 に開催された、PHP カンファレンス香川 2024 に参加した。
- </p>
- </section>
- <footer class="entry-footer">
- <time datetime="2024-05-11">2024-05-11</time> 投稿
- <ul class="entry-tags">
- <li class="tag">
- <span class="tag-inner">カンファレンス</span>
- </li>
- <li class="tag">
- <span class="tag-inner">PHP</span>
- </li>
- <li class="tag">
- <span class="tag-inner">PHP カンファレンス香川</span>
- </li>
- </ul>
- </footer>
- </a>
- </article>
<nav class="pagination">
<div class="pagination-prev">
<a href="/posts/">前へ</a>
diff --git a/services/nuldoc/public/blog/posts/2025-12-06/archive-dynamic-site-with-wget.md b/services/nuldoc/public/blog/posts/2025-12-06/archive-dynamic-site-with-wget.md
new file mode 100644
index 0000000..164d52f
--- /dev/null
+++ b/services/nuldoc/public/blog/posts/2025-12-06/archive-dynamic-site-with-wget.md
@@ -0,0 +1,100 @@
+---
+[article]
+uuid = "02f33085-d81e-4b94-b247-e120ec6e809c"
+title = "wget を使って動的サイトを静的サイトにアーカイブする"
+description = "運用停止した動的サイトを wget でクロールし、静的ファイルのみで配信できるようにした。"
+tags = [
+]
+
+[[article.revisions]]
+date = "2025-12-06"
+remark = "公開"
+---
+# はじめに {#intro}
+
+2024 年に開催された [PHPerKaigi 2024](https://phperkaigi.jp/2024/) において、コードゴルフ企画が開催された。
+私はシステムの開発と当日の運用を担当し、 https://t.nil.ninja/phperkaigi/2024/golf/ でサイトを公開した。
+
+カンファレンスの終了に伴ってこちらのサイトも新規の回答は締め切ったが、以前としてシステムは動的なサイトとして動いていた。
+
+サーバのリソースがもったいないので、このたび wget コマンドを用いてアーカイブし、静的なファイルを Nginx で配信するだけの構成とした。
+
+
+# アーカイブする {#archive}
+
+* 元々の動的サイトに対応するリポジトリはこちら: https://github.com/nsfisis/phperkaigi-2024-albatross
+* 移行後の静的サイトに対応するリポジトリはこちら: https://github.com/nsfisis/phperkaigi-2024-albatross-archive
+
+元々の動的サイトは PHP で構築されたウェブサイト部分と、投稿されたゴルフの回答を実行してテストするサンドボックス環境部分に分かれていた。
+
+新規の投稿を締め切った今、必要なのは問題文や結果を表示する HTML とそれに付随する JavaScript、CSS、画像などの静的ファイルのみである。
+
+wget コマンドを使うと、必要な静的ファイルを集める作業をほとんどすべて自動でおこなうことができる。
+
+今回使用したスクリプトはこちら:
+https://github.com/nsfisis/phperkaigi-2024-albatross-archive/blob/cc837f6d2109555e2392016e8f6820fb5fd46dd6/archive.sh
+
+```bash
+# 指定した URL からスタートしてリンクを辿りながら全ファイルをファイルに書き出す
+#
+# --mirror リンクを再帰的に辿ってダウンロードする
+# --page-requisites CSS や画像等も含めて HTML から参照されている全ファイルをダウンロードする
+# --convert-links リンクを相対リンクへ変換する
+# --adjust-extension URL に拡張子が無くてもいい感じに推測する
+# --no-parent 親ディレクトリは見に行かない
+# --no-wait=1 リクエスト間で 1 秒待機する
+# -P ./archive/ 指定したディレクトリに保存する
+wget \
+ --mirror \
+ --page-requisites \
+ --convert-links \
+ --adjust-extension \
+ --no-parent \
+ --wait=1 \
+ -P ./archive/ \
+ https://t.nil.ninja/phperkaigi/2024/golf/
+
+# ディレクトリ構造を調整する
+mv ./archive/t.nil.ninja/phperkaigi/2024/golf/* ./archive
+rmdir ./archive/t.nil.ninja/phperkaigi/2024/golf/
+rmdir ./archive/t.nil.ninja/phperkaigi/2024/
+rmdir ./archive/t.nil.ninja/phperkaigi/
+rmdir ./archive/t.nil.ninja/
+
+mkdir -p ./archive/api/quizzes/{1,2,3}
+
+# 動的な API エンドポイントを叩いて結果を JSON ファイルとして保存する
+wget -O ./archive/api/quizzes/1/chart.json https://t.nil.ninja/phperkaigi/2024/golf/api/quizzes/1/chart
+wget -O ./archive/api/quizzes/2/chart.json https://t.nil.ninja/phperkaigi/2024/golf/api/quizzes/2/chart
+wget -O ./archive/api/quizzes/3/chart.json https://t.nil.ninja/phperkaigi/2024/golf/api/quizzes/3/chart
+
+# 上記 API を叩いている箇所を、落としてきた静的ファイルを参照するように変更する
+sed -i -e 's#/chart`#/chart.json`#' ./archive/assets/chart.js
+```
+
+このように wget に適切なオプションを渡すことで、指定したページから遷移可能なページを再帰的に辿っていき、サイト内の全ページをファイルへ落とすことができる。
+今回のサイトにはページ遷移では辿り着けないページがあったが (管理画面など)、運用が停止している今そういったページはアーカイブしなくてもよい。
+
+あとはこのファイルを適当にサーブしてやればよい。
+
+```nginx
+server {
+ listen 80 default;
+ listen [::]:80;
+
+ charset UTF-8;
+
+ location /phperkaigi/2024/golf/ {
+ alias /archive/;
+ }
+}
+```
+
+
+# おわりに {#outro}
+
+当初はリンクを再帰的に辿るようなスクリプトを手で書いていたのだが、wget を使うことではるかに簡単な手順でサイト全体のアーカイブが実施できた。
+
+JavaScript から動的にバックエンドの Web API を叩いている箇所については wget だけだと難しいので、複雑なサイトの場合はここが課題となるだろう。
+
+カンファレンスの企画用に作成した運用停止済みのシステムは他にもあるので、それらも順次アーカイブ化を進めていこうと思う。
diff --git a/services/nuldoc/public/blog/posts/2025-12-06/archive-dynamic-site-with-wget/index.html b/services/nuldoc/public/blog/posts/2025-12-06/archive-dynamic-site-with-wget/index.html
new file mode 100644
index 0000000..e857c5c
--- /dev/null
+++ b/services/nuldoc/public/blog/posts/2025-12-06/archive-dynamic-site-with-wget/index.html
@@ -0,0 +1,178 @@
+<!DOCTYPE html>
+<html lang="ja-JP">
+ <head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta name="author" content="nsfisis">
+ <meta name="copyright" content="&copy; 2025 nsfisis">
+ <meta name="description" content="運用停止した動的サイトを wget でクロールし、静的ファイルのみで配信できるようにした。">
+ <meta property="og:type" content="article">
+ <meta property="og:title" content="wget を使って動的サイトを静的サイトにアーカイブする|REPL: Rest-Eat-Program Loop">
+ <meta property="og:description" content="運用停止した動的サイトを wget でクロールし、静的ファイルのみで配信できるようにした。">
+ <meta property="og:site_name" content="REPL: Rest-Eat-Program Loop">
+ <meta property="og:locale" content="ja_JP">
+ <meta name="Hatena::Bookmark" content="nocomment">
+ <link rel="icon" type="image/svg+xml" href="/favicon.svg">
+ <title>wget を使って動的サイトを静的サイトにアーカイブする|REPL: Rest-Eat-Program Loop</title>
+ <link rel="stylesheet" href="/style.css?h=c171793a210d62f7ff2ddf54208f34e5">
+ </head>
+ <body class="single">
+ <header class="header">
+ <div class="site-logo">
+ <a href="https://nsfisis.dev/">nsfisis.dev</a>
+ </div>
+ <div class="site-name">
+ REPL: Rest-Eat-Program Loop
+ </div>
+ <nav class="nav">
+ <ul>
+ <li>
+ <a href="https://about.nsfisis.dev/">About</a>
+ </li>
+ <li>
+ <a href="/posts/">Posts</a>
+ </li>
+ <li>
+ <a href="/tags/">Tags</a>
+ </li>
+ </ul>
+ </nav>
+ </header>
+ <main class="main">
+ <article class="post-single">
+ <header class="post-header">
+ <h1 class="post-title">wget を使って動的サイトを静的サイトにアーカイブする</h1>
+ </header>
+ <nav class="toc">
+ <h2>目次</h2>
+ <ul>
+ <li>
+ <a href="#section--intro">はじめに</a>
+ </li>
+ <li>
+ <a href="#section--archive">アーカイブする</a>
+ </li>
+ <li>
+ <a href="#section--outro">おわりに</a>
+ </li>
+ </ul>
+ </nav>
+ <div class="post-content">
+ <section id="changelog">
+ <h2><a href="#changelog">更新履歴</a></h2>
+ <ol>
+ <li class="revision">
+ <time datetime="2025-12-06">2025-12-06</time>: 公開
+ </li>
+ </ol>
+ </section>
+ <section id="section--intro">
+ <h2><a href="#section--intro">はじめに</a></h2>
+ <p>
+ 2024 年に開催された <a href="https://phperkaigi.jp/2024/" rel="noreferrer" target="_blank">PHPerKaigi 2024</a> において、コードゴルフ企画が開催された。私はシステムの開発と当日の運用を担当し、 <a class="url" href="https://t.nil.ninja/phperkaigi/2024/golf/" rel="noreferrer" target="_blank">https://t.nil.ninja/phperkaigi/2024/golf/</a> でサイトを公開した。
+ </p>
+ <p>
+ カンファレンスの終了に伴ってこちらのサイトも新規の回答は締め切ったが、以前としてシステムは動的なサイトとして動いていた。
+ </p>
+ <p>
+ サーバのリソースがもったいないので、このたび wget コマンドを用いてアーカイブし、静的なファイルを Nginx で配信するだけの構成とした。
+ </p>
+ </section>
+ <section id="section--archive">
+ <h2><a href="#section--archive">アーカイブする</a></h2>
+ <ul>
+ <li>
+ 元々の動的サイトに対応するリポジトリはこちら: <a class="url" href="https://github.com/nsfisis/phperkaigi-2024-albatross" rel="noreferrer" target="_blank">https://github.com/nsfisis/phperkaigi-2024-albatross</a>
+ </li>
+ <li>
+ 移行後の静的サイトに対応するリポジトリはこちら: <a class="url" href="https://github.com/nsfisis/phperkaigi-2024-albatross-archive" rel="noreferrer" target="_blank">https://github.com/nsfisis/phperkaigi-2024-albatross-archive</a>
+ </li>
+ </ul>
+ <p>
+ 元々の動的サイトは PHP で構築されたウェブサイト部分と、投稿されたゴルフの回答を実行してテストするサンドボックス環境部分に分かれていた。
+ </p>
+ <p>
+ 新規の投稿を締め切った今、必要なのは問題文や結果を表示する HTML とそれに付随する JavaScript、CSS、画像などの静的ファイルのみである。
+ </p>
+ <p>
+ wget コマンドを使うと、必要な静的ファイルを集める作業をほとんどすべて自動でおこなうことができる。
+ </p>
+ <p>
+ 今回使用したスクリプトはこちら: <a class="url" href="https://github.com/nsfisis/phperkaigi-2024-albatross-archive/blob/cc837f6d2109555e2392016e8f6820fb5fd46dd6/archive.sh" rel="noreferrer" target="_blank">https://github.com/nsfisis/phperkaigi-2024-albatross-archive/blob/cc837f6d2109555e2392016e8f6820fb5fd46dd6/archive.sh</a>
+ </p>
+ <div class="codeblock">
+ <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#6A737D"># 指定した URL からスタートしてリンクを辿りながら全ファイルをファイルに書き出す</span></span>
+<span class="line"><span style="color:#6A737D">#</span></span>
+<span class="line"><span style="color:#6A737D"># --mirror リンクを再帰的に辿ってダウンロードする</span></span>
+<span class="line"><span style="color:#6A737D"># --page-requisites CSS や画像等も含めて HTML から参照されている全ファイルをダウンロードする</span></span>
+<span class="line"><span style="color:#6A737D"># --convert-links リンクを相対リンクへ変換する</span></span>
+<span class="line"><span style="color:#6A737D"># --adjust-extension URL に拡張子が無くてもいい感じに推測する</span></span>
+<span class="line"><span style="color:#6A737D"># --no-parent 親ディレクトリは見に行かない</span></span>
+<span class="line"><span style="color:#6A737D"># --no-wait=1 リクエスト間で 1 秒待機する</span></span>
+<span class="line"><span style="color:#6A737D"># -P ./archive/ 指定したディレクトリに保存する</span></span>
+<span class="line"><span style="color:#6F42C1">wget</span><span style="color:#005CC5"> \</span></span>
+<span class="line"><span style="color:#005CC5"> --mirror</span><span style="color:#005CC5"> \</span></span>
+<span class="line"><span style="color:#005CC5"> --page-requisites</span><span style="color:#005CC5"> \</span></span>
+<span class="line"><span style="color:#005CC5"> --convert-links</span><span style="color:#005CC5"> \</span></span>
+<span class="line"><span style="color:#005CC5"> --adjust-extension</span><span style="color:#005CC5"> \</span></span>
+<span class="line"><span style="color:#005CC5"> --no-parent</span><span style="color:#005CC5"> \</span></span>
+<span class="line"><span style="color:#005CC5"> --wait=1</span><span style="color:#005CC5"> \</span></span>
+<span class="line"><span style="color:#005CC5"> -P</span><span style="color:#032F62"> ./archive/</span><span style="color:#005CC5"> \</span></span>
+<span class="line"><span style="color:#032F62"> https://t.nil.ninja/phperkaigi/2024/golf/</span></span>
+<span class="line"></span>
+<span class="line"><span style="color:#6A737D"># ディレクトリ構造を調整する</span></span>
+<span class="line"><span style="color:#6F42C1">mv</span><span style="color:#032F62"> ./archive/t.nil.ninja/phperkaigi/2024/golf/</span><span style="color:#005CC5">*</span><span style="color:#032F62"> ./archive</span></span>
+<span class="line"><span style="color:#6F42C1">rmdir</span><span style="color:#032F62"> ./archive/t.nil.ninja/phperkaigi/2024/golf/</span></span>
+<span class="line"><span style="color:#6F42C1">rmdir</span><span style="color:#032F62"> ./archive/t.nil.ninja/phperkaigi/2024/</span></span>
+<span class="line"><span style="color:#6F42C1">rmdir</span><span style="color:#032F62"> ./archive/t.nil.ninja/phperkaigi/</span></span>
+<span class="line"><span style="color:#6F42C1">rmdir</span><span style="color:#032F62"> ./archive/t.nil.ninja/</span></span>
+<span class="line"></span>
+<span class="line"><span style="color:#6F42C1">mkdir</span><span style="color:#005CC5"> -p</span><span style="color:#032F62"> ./archive/api/quizzes/{1,2,3}</span></span>
+<span class="line"></span>
+<span class="line"><span style="color:#6A737D"># 動的な API エンドポイントを叩いて結果を JSON ファイルとして保存する</span></span>
+<span class="line"><span style="color:#6F42C1">wget</span><span style="color:#005CC5"> -O</span><span style="color:#032F62"> ./archive/api/quizzes/1/chart.json</span><span style="color:#032F62"> https://t.nil.ninja/phperkaigi/2024/golf/api/quizzes/1/chart</span></span>
+<span class="line"><span style="color:#6F42C1">wget</span><span style="color:#005CC5"> -O</span><span style="color:#032F62"> ./archive/api/quizzes/2/chart.json</span><span style="color:#032F62"> https://t.nil.ninja/phperkaigi/2024/golf/api/quizzes/2/chart</span></span>
+<span class="line"><span style="color:#6F42C1">wget</span><span style="color:#005CC5"> -O</span><span style="color:#032F62"> ./archive/api/quizzes/3/chart.json</span><span style="color:#032F62"> https://t.nil.ninja/phperkaigi/2024/golf/api/quizzes/3/chart</span></span>
+<span class="line"></span>
+<span class="line"><span style="color:#6A737D"># 上記 API を叩いている箇所を、落としてきた静的ファイルを参照するように変更する</span></span>
+<span class="line"><span style="color:#6F42C1">sed</span><span style="color:#005CC5"> -i</span><span style="color:#005CC5"> -e</span><span style="color:#032F62"> 's#/chart`#/chart.json`#'</span><span style="color:#032F62"> ./archive/assets/chart.js</span></span></code></pre>
+ </div>
+ <p>
+ このように wget に適切なオプションを渡すことで、指定したページから遷移可能なページを再帰的に辿っていき、サイト内の全ページをファイルへ落とすことができる。今回のサイトにはページ遷移では辿り着けないページがあったが (管理画面など)、運用が停止している今そういったページはアーカイブしなくてもよい。
+ </p>
+ <p>
+ あとはこのファイルを適当にサーブしてやればよい。
+ </p>
+ <div class="codeblock">
+ <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49">server</span><span style="color:#24292E"> {</span></span>
+<span class="line"><span style="color:#D73A49"> listen </span><span style="color:#005CC5">80</span><span style="color:#005CC5"> default</span><span style="color:#24292E">;</span></span>
+<span class="line"><span style="color:#D73A49"> listen </span><span style="color:#24292E">[::]:80;</span></span>
+<span class="line"></span>
+<span class="line"><span style="color:#D73A49"> charset </span><span style="color:#24292E">UTF-8;</span></span>
+<span class="line"></span>
+<span class="line"><span style="color:#D73A49"> location</span><span style="color:#6F42C1"> /phperkaigi/2024/golf/ </span><span style="color:#24292E">{</span></span>
+<span class="line"><span style="color:#D73A49"> alias </span><span style="color:#24292E">/archive/;</span></span>
+<span class="line"><span style="color:#24292E"> }</span></span>
+<span class="line"><span style="color:#24292E">}</span></span></code></pre>
+ </div>
+ </section>
+ <section id="section--outro">
+ <h2><a href="#section--outro">おわりに</a></h2>
+ <p>
+ 当初はリンクを再帰的に辿るようなスクリプトを手で書いていたのだが、wget を使うことではるかに簡単な手順でサイト全体のアーカイブが実施できた。
+ </p>
+ <p>
+ JavaScript から動的にバックエンドの Web API を叩いている箇所については wget だけだと難しいので、複雑なサイトの場合はここが課題となるだろう。
+ </p>
+ <p>
+ カンファレンスの企画用に作成した運用停止済みのシステムは他にもあるので、それらも順次アーカイブ化を進めていこうと思う。
+ </p>
+ </section>
+ </div>
+ </article>
+ </main>
+ <footer class="footer">
+ &copy; 2021 nsfisis
+ </footer>
+ </body>
+</html>
diff --git a/services/nuldoc/public/blog/posts/3/index.html b/services/nuldoc/public/blog/posts/3/index.html
index f6fe5b7..31096bb 100644
--- a/services/nuldoc/public/blog/posts/3/index.html
+++ b/services/nuldoc/public/blog/posts/3/index.html
@@ -70,6 +70,32 @@
</div>
</nav>
<article class="post-entry">
+ <a href="/posts/2024-05-11/phpconkagawa-2024-report/">
+ <header class="entry-header">
+ <h2>PHP カンファレンス香川 2024 参加レポ</h2>
+ </header>
+ <section class="entry-content">
+ <p>
+ 2024-05-11 に開催された、PHP カンファレンス香川 2024 に参加した。
+ </p>
+ </section>
+ <footer class="entry-footer">
+ <time datetime="2024-05-11">2024-05-11</time> 投稿
+ <ul class="entry-tags">
+ <li class="tag">
+ <span class="tag-inner">カンファレンス</span>
+ </li>
+ <li class="tag">
+ <span class="tag-inner">PHP</span>
+ </li>
+ <li class="tag">
+ <span class="tag-inner">PHP カンファレンス香川</span>
+ </li>
+ </ul>
+ </footer>
+ </a>
+ </article>
+ <article class="post-entry">
<a href="/posts/2024-04-29/zsh-file-completion-for-composer-custom-commands/">
<header class="entry-header">
<h2>【Zsh】 Composer のカスタムコマンドに対する Zsh 補完で引数にファイルを補完させる</h2>
@@ -283,21 +309,6 @@
</footer>
</a>
</article>
- <article class="post-entry">
- <a href="/posts/2023-12-31/2023-reflections/">
- <header class="entry-header">
- <h2>2023年の振り返り</h2>
- </header>
- <section class="entry-content">
- <p>
- 2023年にやったことを振り返る
- </p>
- </section>
- <footer class="entry-footer">
- <time datetime="2023-12-31">2023-12-31</time> 投稿
- </footer>
- </a>
- </article>
<nav class="pagination">
<div class="pagination-prev">
<a href="/posts/2/">前へ</a>
diff --git a/services/nuldoc/public/blog/posts/4/index.html b/services/nuldoc/public/blog/posts/4/index.html
index 8e6476b..457e608 100644
--- a/services/nuldoc/public/blog/posts/4/index.html
+++ b/services/nuldoc/public/blog/posts/4/index.html
@@ -70,6 +70,21 @@
</div>
</nav>
<article class="post-entry">
+ <a href="/posts/2023-12-31/2023-reflections/">
+ <header class="entry-header">
+ <h2>2023年の振り返り</h2>
+ </header>
+ <section class="entry-content">
+ <p>
+ 2023年にやったことを振り返る
+ </p>
+ </section>
+ <footer class="entry-footer">
+ <time datetime="2023-12-31">2023-12-31</time> 投稿
+ </footer>
+ </a>
+ </article>
+ <article class="post-entry">
<a href="/posts/2023-12-03/isucon-13/">
<header class="entry-header">
<h2>ISUCON 13 に参加した</h2>
@@ -260,26 +275,6 @@
</footer>
</a>
</article>
- <article class="post-entry">
- <a href="/posts/2022-10-28/setup-server-for-this-site/">
- <header class="entry-header">
- <h2>【備忘録】 このサイト用の VPS をセットアップしたときのメモ</h2>
- </header>
- <section class="entry-content">
- <p>
- GitHub Pages でホストしていたこのサイトを VPS へ移行したので、そのときにやったことのメモ。99 % 自分用。
- </p>
- </section>
- <footer class="entry-footer">
- <time datetime="2022-10-28">2022-10-28</time> 投稿、<time datetime="2023-08-30">2023-08-30</time> 更新
- <ul class="entry-tags">
- <li class="tag">
- <span class="tag-inner">備忘録</span>
- </li>
- </ul>
- </footer>
- </a>
- </article>
<nav class="pagination">
<div class="pagination-prev">
<a href="/posts/3/">前へ</a>
diff --git a/services/nuldoc/public/blog/posts/5/index.html b/services/nuldoc/public/blog/posts/5/index.html
index a68bf58..dc3a946 100644
--- a/services/nuldoc/public/blog/posts/5/index.html
+++ b/services/nuldoc/public/blog/posts/5/index.html
@@ -67,6 +67,26 @@
</div>
</nav>
<article class="post-entry">
+ <a href="/posts/2022-10-28/setup-server-for-this-site/">
+ <header class="entry-header">
+ <h2>【備忘録】 このサイト用の VPS をセットアップしたときのメモ</h2>
+ </header>
+ <section class="entry-content">
+ <p>
+ GitHub Pages でホストしていたこのサイトを VPS へ移行したので、そのときにやったことのメモ。99 % 自分用。
+ </p>
+ </section>
+ <footer class="entry-footer">
+ <time datetime="2022-10-28">2022-10-28</time> 投稿、<time datetime="2023-08-30">2023-08-30</time> 更新
+ <ul class="entry-tags">
+ <li class="tag">
+ <span class="tag-inner">備忘録</span>
+ </li>
+ </ul>
+ </footer>
+ </a>
+ </article>
+ <article class="post-entry">
<a href="/posts/2022-10-23/phperkaigi-2023-unused-token-quiz-1/">
<header class="entry-header">
<h2>PHPerKaigi 2023: ボツになったトークン問題 その 1</h2>
@@ -266,26 +286,6 @@
</footer>
</a>
</article>
- <article class="post-entry">
- <a href="/posts/2021-10-02/ruby-detect-running-implementation/">
- <header class="entry-header">
- <h2>【Ruby】 自身を実行している処理系の種類を判定する</h2>
- </header>
- <section class="entry-content">
- <p>
- Ruby には複数の実装があるが、自身を実行している処理系の種類をスクリプト上からどのように判定すればよいだろうか。
- </p>
- </section>
- <footer class="entry-footer">
- <time datetime="2021-10-02">2021-10-02</time> 投稿
- <ul class="entry-tags">
- <li class="tag">
- <span class="tag-inner">Ruby</span>
- </li>
- </ul>
- </footer>
- </a>
- </article>
<nav class="pagination">
<div class="pagination-prev">
<a href="/posts/4/">前へ</a>
diff --git a/services/nuldoc/public/blog/posts/6/index.html b/services/nuldoc/public/blog/posts/6/index.html
index 1ccf8c4..e2f3ff3 100644
--- a/services/nuldoc/public/blog/posts/6/index.html
+++ b/services/nuldoc/public/blog/posts/6/index.html
@@ -63,6 +63,26 @@
</div>
</nav>
<article class="post-entry">
+ <a href="/posts/2021-10-02/ruby-detect-running-implementation/">
+ <header class="entry-header">
+ <h2>【Ruby】 自身を実行している処理系の種類を判定する</h2>
+ </header>
+ <section class="entry-content">
+ <p>
+ Ruby には複数の実装があるが、自身を実行している処理系の種類をスクリプト上からどのように判定すればよいだろうか。
+ </p>
+ </section>
+ <footer class="entry-footer">
+ <time datetime="2021-10-02">2021-10-02</time> 投稿
+ <ul class="entry-tags">
+ <li class="tag">
+ <span class="tag-inner">Ruby</span>
+ </li>
+ </ul>
+ </footer>
+ </a>
+ </article>
+ <article class="post-entry">
<a href="/posts/2021-10-02/ruby-then-keyword-and-case-in/">
<header class="entry-header">
<h2>【Ruby】 then キーワードと case in</h2>
diff --git a/services/nuldoc/public/blog/posts/atom.xml b/services/nuldoc/public/blog/posts/atom.xml
index 4c02c04..65e961f 100644
--- a/services/nuldoc/public/blog/posts/atom.xml
+++ b/services/nuldoc/public/blog/posts/atom.xml
@@ -7,7 +7,15 @@
<author>
<name>nsfisis</name>
</author>
- <updated>2025-11-27T00:00:00+09:00</updated>
+ <updated>2025-12-06T00:00:00+09:00</updated>
+ <entry>
+ <id>urn:uuid:02f33085-d81e-4b94-b247-e120ec6e809c</id>
+ <link rel="alternate" href="https://blog.nsfisis.dev/posts/2025-12-06/archive-dynamic-site-with-wget/"></link>
+ <title>wget を使って動的サイトを静的サイトにアーカイブする</title>
+ <summary>運用停止した動的サイトを wget でクロールし、静的ファイルのみで配信できるようにした。</summary>
+ <published>2025-12-06T00:00:00+09:00</published>
+ <updated>2025-12-06T00:00:00+09:00</updated>
+ </entry>
<entry>
<id>urn:uuid:2ed2d400-b3f6-48bc-af27-19d9042875a0</id>
<link rel="alternate" href="https://blog.nsfisis.dev/posts/2025-11-27/anybatross-writeup/"></link>
diff --git a/services/nuldoc/public/blog/posts/index.html b/services/nuldoc/public/blog/posts/index.html
index dc28dcf..7ea8cc9 100644
--- a/services/nuldoc/public/blog/posts/index.html
+++ b/services/nuldoc/public/blog/posts/index.html
@@ -63,6 +63,21 @@
</div>
</nav>
<article class="post-entry">
+ <a href="/posts/2025-12-06/archive-dynamic-site-with-wget/">
+ <header class="entry-header">
+ <h2>wget を使って動的サイトを静的サイトにアーカイブする</h2>
+ </header>
+ <section class="entry-content">
+ <p>
+ 運用停止した動的サイトを wget でクロールし、静的ファイルのみで配信できるようにした。
+ </p>
+ </section>
+ <footer class="entry-footer">
+ <time datetime="2025-12-06">2025-12-06</time> 投稿
+ </footer>
+ </a>
+ </article>
+ <article class="post-entry">
<a href="/posts/2025-11-27/anybatross-writeup/">
<header class="entry-header">
<h2>カヤックさん開催のコードゴルフコンテスト Anybatross に参加して優勝した</h2>
@@ -264,26 +279,6 @@
</footer>
</a>
</article>
- <article class="post-entry">
- <a href="/posts/2025-03-27/zip-function-like-command-paste-command/">
- <header class="entry-header">
- <h2>zip 関数のようなコマンド paste</h2>
- </header>
- <section class="entry-content">
- <p>
- zip 関数のような動きをする paste コマンドについてのメモ。
- </p>
- </section>
- <footer class="entry-footer">
- <time datetime="2025-03-27">2025-03-27</time> 投稿
- <ul class="entry-tags">
- <li class="tag">
- <span class="tag-inner">備忘録</span>
- </li>
- </ul>
- </footer>
- </a>
- </article>
<nav class="pagination">
<div class="pagination-prev">
</div>