記事
消えたブログをWebアーカイブから復元する【前編】――GAとCodexを使って記事を取り戻した話
この記事の目次 9項目
前回の記事で書いた通り、WordPressの復旧後、FTP操作のミスによってブログのコンテンツを削除してしまった。
バックアップからの復旧も試みたが、必要なデータが含まれておらず、元には戻せなかった。
これでブログも終わりか。
ここ数年は更新も途絶えていたし、ちょうどよい節目なのかもしれない。そう考えて、一時はブログを閉鎖した。
ただ、意外と割り切れないものだった。
ブラウザに残っているブログ関連のブックマークなどが目に入るたびに、「ああ、もうこのブログは閉じてしまったんだなぁ」と、少し寂しくなる。
10年近く使ってきたドメインには、自分で思っていた以上に愛着があったらしい。
そんなとき、以前の仕事で、Web上の「魚拓」を使って他社サイトの過去と現在を見比べていたことを思い出した。
過去のページが残っているなら、そこからブログを作り直せるのではないか。
今回は、その思いつきからWebアーカイブを調べ、Codexで回収バッチを作り、記事と画像を取り戻すまでの話を書いていく。
WordPressは失っても、公開していたページは残っていた
調べてみると、Internet Archiveの「Wayback Machine」に、このブログの過去のページが保存されていた。
今回、復元の起点にしたのは、以下のスナップショットだ。
見覚えのある記事タイトルや画像が並んでいる。
もう消えたと思っていたものが、別の場所には残っていた。これだけでも、ちょっと嬉しかった。
ただし、アーカイブに残っているのは、WordPressのバックアップではない。
WordPressでは、データベースに保存された記事や設定を使って、閲覧用のHTMLを生成する。一方、Webアーカイブに残っているのは、主にその生成後のページや、収集された画像などだ。
元の管理画面やプラグイン設定を復旧することは難しい。
それでも、自分が残したいのは記事の本文と画像だ。それらを取り出せるなら、WordPressを再び動かす必要はない。
公開されていたページから必要なコンテンツを取り出し、別の仕組みで組み立て直す。今回は、その方針で進めることにした。
最初の課題は「どの記事があったのか」
トップページが残っていても、それだけで全記事を復元できるわけではない。
個別記事が保存されているか、画像も残っているかは、それぞれ調べる必要がある。
Wayback Machineには、保存されたURLや日時などを調べる「CDX API」がある。公開されている保存履歴を調査する用途で、今回はこれを利用した。
最初は、ドメイン配下の保存URLをまとめて取得しようと考えた。
ただ、実際には一覧取得で503エラーになることがあり、思ったようには進まない。503はサービス側が一時的に処理できない場合などに返されるエラーで、それだけで「保存データがない」と判断することはできない。
ここで、別の手がかりを使うことにした。
Google Analyticsには、ブログにアクセスされたページのパスが残っている。
これなら、「このブログにどんなURLがあったか」を先に整理できる。
GAのアクセス履歴を、復元対象の一覧に使う
Google Analyticsから、取得できる全期間を対象にCSVを出力した。
使ったのは「ページパスとスクリーン クラス」と「表示回数」などの項目だ。
例えば、次のようなパスが分かれば、元URLを組み立てられる。
ページパス:
/2020/08/26/post-2234/
元URL:
https://yolo-kiyoshi.com/2020/08/26/post-2234/
これを起点に、URLごとのアーカイブ保存状況を調べる。
ドメイン全体から記事を探すよりも、調査対象と進捗を管理しやすい。表示回数もあるので、よく読まれていたページから優先して処理する、といった使い方もできる。
もっとも、GAの一覧が全記事を網羅しているとは限らない。計測期間や設定によって、記録されていないページもあり得る。
今回は、まず手元にあるアクセス履歴を復元対象の起点にする、という位置付けだ。
Codexに依頼したのは、止まっても続きから動くバッチ
回収処理は、PythonとCDX APIを使って実装した。
コードの作成にはCodexを活用したが、最初に考えたのはHTMLの解析方法よりも、処理をどう止め、どう再開するかだった。
個人ブログとはいえ、記事に加えて画像も調査すると、それなりのリクエスト数になる。途中でエラーが出るたびに最初から実行し直すのは避けたい。
そこで、主に次の条件を伝えた。
- リクエストの間に待機を入れ、並列で大量取得しない。
- 一時的な失敗は、待機時間を延ばして再試行する。
- 処理状態をSQLiteに保存し、途中から再開できるようにする。
- 「保存候補が見つからない」と「通信に失敗した」を区別する。
- 元URL、採用した保存日時、取得結果を追跡できるようにする。
処理の流れは、次のようになる。
特に大事だったのは、APIがエラーになったことを、記事が存在しないことと混同しない設計だ。
これは、Webアーカイブに限らず、外部サービスからデータを集めるときには共通する話だと思う。
記事のHTMLが戻っても、画像まで戻るとは限らない
記事のHTMLを取得できると、本文やタイトルに加えて、画像の参照先も分かる。
ただし、HTMLに画像URLが書かれていても、画像ファイルそのものがアーカイブに保存されているとは限らない。
例えば、HTMLに次の記述が残っていたとする。
<img src="/wp/wp-content/uploads/2020/08/example.png">
この場合、画像URLの存在は分かる。しかし、そのURLの画像データを実際に取得できるかは、別に確認する必要がある。
そのため、記事HTMLの回収後に画像URLを抽出し、画像を回収する処理も行った。
「画像のURLを発見した」「画像ファイルを保存できた」「保存したものが画像として扱える」という段階を分けて確認する。
一覧にURLが並んでいるだけでは、復元できたことにはならないのだ。
どこまで過去を探すかは、品質と時間のトレードオフ
今回は、素早くブログを復活させることを優先し、スナップショットの基準日を固定して記事や画像を回収した。
ここには、もう少し改善できる余地がある。
ある時点で取得できなかった画像でも、別の保存日時をたどれば見つかるかもしれない。記事についても、異なるスナップショットには、欠けていた情報が残っている可能性がある。
一方、保存履歴を広く調べるほど、リクエスト数と処理時間は増える。複数時点のデータを組み合わせれば、記事と画像の内容が食い違う可能性にも気を配る必要がある。
今回は、最初から完全復元を目指して調査を広げ続けるよりも、まず読めるブログを復活させる方を選んだ。
追加調査で回収率を上げられる余地はあると思うが、どこまで時間をかけるかは悩ましいところだ。
記事候補の87.5%、画像URLの62.5%を回収できた
2026年11月2日時点で、DBと保存ファイルを照合した結果は、次のようになった。
| 対象 | 調査・抽出数 | 回収済み | 回収率 |
|---|---|---|---|
| 記事候補のURL | 184件 | 161件 | 87.5% |
| 一覧ページを含む全URL | 254件 | 222件 | 87.4% |
| HTMLから抽出した画像URL | 728件 | 455件 | 62.5% |
URL単位の集計と、保存ファイルの数は一致しない。
重複URLをまとめると、記事候補のHTMLは156件。一覧ページ54件と合わせて、210件のHTMLを保存できた。画像は455 URL分で、実ファイルは453個だった。
画像については、URL単位の回収率だけを見ると、少し物足りなく感じるかもしれない。
ただ、同じ画像は複数の記事や一覧ページでも使われている。HTML内の画像参照を数えると、5,429箇所のうち4,868箇所、89.7%の参照箇所に対応する画像を回収できていた。
画像URLの回収率と、画像参照箇所のカバー率では、見え方がかなり違う。
未回収の画像URLは273件で、内訳は次の通りだ。
| 状態 | 件数 |
|---|---|
| 404/410応答 | 271件 |
| 画像として不正な応答 | 1件 |
| 再試行失敗による保留 | 1件 |
ここでの404/410も、今回の取得条件で回収できなかったという結果だ。別の保存日時まで調べれば見つかる可能性は残っている。
また、保存したHTMLと画像、合計665ファイルについては、ファイルの存在と、記録したハッシュとの一致を確認した。
これは保存データの整合性確認であって、記事本文が完全に戻ったことや、当時の表示を再現できたことを保証するものではない。
今回の回収率は、GA由来の記事候補と、取得したHTMLから見つかった画像を母数にした数字であり、ブログ全体の完全復元率ではない。
それでも、一度は全部失ったと思っていたブログから、これだけのコンテンツを取り戻せたのは大きかった。
AIに任せる前に、何を記録するかを決める
実装はCodexにかなり任せられた。
ただ、「アーカイブから記事を取ってきて」と伝えるだけでは、あとで結果を判断しにくくなる。
どのURLを調査したのか。どの保存日時を採用したのか。何が取得できず、それは通信失敗なのか、保存候補が見つからなかったのか。
こうした情報が残っていれば、処理を途中から再開できるし、追加調査の対象も決められる。
今回、自分が考える必要があったのは、細かな構文以上に、何を成功とし、何を未完了として残すかだった。
それを具体的に伝えることで、Codexに実装を任せやすくなったと感じる。
次は、取り戻した記事を公開する
ここまでで、記事のHTMLと画像を回収できた。
ただ、回収したHTMLには当時のテーマやアーカイブ由来の要素も含まれる。ファイルを集めただけで、そのまま新しいブログが完成するわけではない。
次に必要なのは、取り戻したコンテンツを整理し、元のURLで読めるサイトとして公開することだ。
後編では、AstroとAWSを使った静的サイトの構成、Terraformによるインフラ管理、GitHub Actionsによる公開の仕組みを紹介する。
一度は閉じたブログを、今後も更新できる形に作り直す話だ。