SNSのリンク切れをWayback Machine CDXで調べる方法
更新日

消えた投稿や古いSNSリンクを調べるとき、まず確認したいのは「Wayback Machineに記録が残っているか」です。CDXデータはそのためのアーカイブ索引で、保存URL、タイムスタンプ、ステータスコード、MIMEタイプ、digest、レスポンス長を返します。ただし、CDXだけではページ内容の証明にはなりません。候補を見つけた後に、URL整理、重複排除、可視化、スナップショット確認まで進めます。
| ステップ | やること | 重要な理由 |
|---|---|---|
| 1. 種URLを集める | 元URL、出典、収集日、対象タイプを保存する | 来歴を追えるようにする |
| 2. URLの揺れを正規化する | 追跡パラメータを落としつつ、プラットフォーム差は残す | 偽の重複を減らす |
| 3. CDXを問い合わせる | タイムスタンプ、元URL、MIMEタイプ、ステータスコード、digest、長さを取得する | 生のアーカイブデータを作る |
| 4. 行を補強する | 時刻を解析し、プラットフォームとプロフィール/投稿/スレッドを分類する | 分析しやすい形にする |
| 5. 慎重に重複排除する | digest、URL、対象グループを比較する | 保存状況を過大評価しない |
| 6. スナップショットを検証する | https://web.archive.org/web/{timestamp}/{original_url} を開く | 索引行と証拠を分ける |
| 7. カバレッジを可視化する | プラットフォーム、状態、日付、対象別にチャート化する | 欠落とレビュー優先度を見つける |
CDXは保存キャプチャの索引レイヤーです。保存ページそのものではなく、図書館の目録に近いものとして扱います。
SNSアーカイブデータが扱いにくい理由
SNSのURLは安定して見えますが、アーカイブ分析では揺れが多く出ます。Twitter/Xの投稿は twitter.com、x.com、mobile.twitter.com のどれかで保存されることがあります。Redditには旧パス、コメントアンカー、クエリ、短縮リンクが混ざり、Instagramではプロフィール、投稿、Reel、埋め込みメディアのパスが分かれます。
同じに見えるURLでも、CDXでは別キーになることがあります。広すぎる検索は無関係なアセットを拾い、狭すぎる検索は別ホスト名のキャプチャを逃します。
主なノイズは、ホスト名や追跡パラメータの揺れ、同一レスポンスの反復キャプチャ、ログイン壁やリダイレクト、CDX行を本文証拠と誤読することです。
目標は完璧なデータではなく、監査できるワークフローです。
公開データの可用性マトリクス
分析前に、この表で言い過ぎを防ぎます。
| データ種別 | Twitter/X | TikTok | ||
|---|---|---|---|---|
| 公開プロフィールのメタデータ | CDXと一部スナップショット | 公開JSONとCDX | CDXと一部スナップショット | CDXと一部スナップショット |
| 公開投稿の本文 | スナップショット次第 | 公開JSONとスナップショット | スナップショット次第 | スナップショット次第 |
| 公開投稿のメディア | ベストエフォート | 比較的扱いやすい | 難しく部分的 | 難しく部分的 |
| 削除済みの公開投稿 | 削除前に保存されていた場合のみ | 削除前に保存されていた場合のみ | まれ | まれ |
| 過去のエンゲージメント数 | スナップショット次第 | 最近のJSONまたはスナップショット次第 | 通常は取得困難 | 通常は取得困難 |
アーカイブデータが強いのは、公開ページの履歴調査です。非公開エクスポートでも完全なアカウント履歴でもなく、欠落記録が存在しなかった証明にもなりません。
CDX APIが返すもの
Wayback CDX APIは、URLパターンに対する索引行を返します。短いクエリ例です。
curl "https://web.archive.org/cdx/search/cdx?url=twitter.com/*/status/*&output=json&fl=timestamp,original,mimetype,statuscode,digest,length&filter=statuscode:200&limit=100"主なフィールドです。
| フィールド | 意味 | 使い道 |
|---|---|---|
timestamp | YYYYMMDDhhmmss形式の保存時刻 | タイムラインを作る |
original | 保存された元URL | 対象URLの復元と正規化 |
mimetype | アーカイブされたレスポンスのMIMEタイプ | HTML、画像、JSON、アセットを分ける |
statuscode | アーカイブが記録したHTTPステータス | リダイレクト、エラー、ブロックを絞る |
digest | コンテンツの指紋 | 同一キャプチャの繰り返しを見つける |
length | レスポンスサイズ | 小さすぎるエラーページや異常値を見つける |
collapse=digest で重複は減らせますが、調査では生データを残し、後から明示的なルールで重複排除する方が扱いやすいです。
データセットを作る
まず、種URLを明示的に用意します。
label,platform,url
example_x_post,x,https://twitter.com/example/status/1234567890
example_reddit_thread,reddit,https://www.reddit.com/r/example/comments/abc123/example_thread/
example_instagram_profile,instagram,https://www.instagram.com/example/source、collection_date、expected_platform、target_type、notes なども追加します。出典情報はデータセットの一部です。
正規化は保守的に行います。追跡ノイズは消し、投稿、コメント、メディアを識別するパスは残します。
from urllib.parse import parse_qsl, urlencode, urlparse, urlunparse
TRACKING_PREFIXES = ("utm_",)
TRACKING_KEYS = {"fbclid", "gclid", "igshid"}
def normalize_url(url: str) -> str:
parsed = urlparse(url.strip())
query = [
(key, value)
for key, value in parse_qsl(parsed.query, keep_blank_values=True)
if key not in TRACKING_KEYS
and not any(key.startswith(prefix) for prefix in TRACKING_PREFIXES)
]
path = parsed.path[:-1] if parsed.path != "/" and parsed.path.endswith("/") else parsed.path
return urlunparse(("https", parsed.netloc.lower(), path, "", urlencode(query), ""))2つのURLが別対象を指す可能性があるなら、無理にまとめず normalized_group でグループ化します。
CDX行をクレンジングして補強する
CDXを書き出したら、タイムスタンプ解析、数値変換、プラットフォーム推定、WaybackスナップショットURL作成を行います。
from urllib.parse import urlparse
import pandas as pd
df = pd.read_csv("social_cdx_export.csv")
df["captured_at"] = pd.to_datetime(
df["timestamp"].astype(str),
format="%Y%m%d%H%M%S",
utc=True,
errors="coerce",
)
df["capture_month"] = df["captured_at"].dt.strftime("%Y-%m")
df["statuscode"] = pd.to_numeric(df["statuscode"], errors="coerce")
df["length"] = pd.to_numeric(df["length"], errors="coerce")
def platform_from_url(url: str) -> str:
host = urlparse(str(url)).netloc.lower()
if "twitter.com" in host or "x.com" in host:
return "x"
if "reddit.com" in host:
return "reddit"
if "instagram.com" in host:
return "instagram"
return "other"
df["platform"] = df["original"].apply(platform_from_url)
df["wayback_url"] = (
"https://web.archive.org/web/"
+ df["timestamp"].astype(str)
+ "/"
+ df["original"].astype(str)
)次に、答えたい問いに合わせて重複排除します。
deduped = (
df.sort_values("captured_at")
.drop_duplicates(subset=["original", "digest"], keep="first")
.copy()
)
duplicate_ratio = 1 - (len(deduped) / len(df))URLが見つかった回数を重視するなら多めに残し、異なる内容状態を見たいなら強めに重複を落とします。
主張する前に検証する
statuscode=200 のCDX行は手がかりであって結論ではありません。実体は元投稿ではなく、ログイン壁、リダイレクト先、アプリシェル、中間ページ、不完全なキャプチャかもしれません。
信頼度は3段階で管理します。
| レベル | 意味 | 使いどころ |
|---|---|---|
| Indexed | CDXが行を返した | 発見とレビュー待ちリスト作成 |
| Retrieved | Waybackスナップショットが開き、意味のある内容を返した | 候補分析 |
| Validated | レビュー担当者が必要な本文やメタデータを確認した | 証拠が必要な作業 |
結論に使う行にはレビュー列を追加します。
| 列 | 目的 |
|---|---|
wayback_url | 直接開けるスナップショットURL |
validation_status | indexed、retrieved、valid_snapshot、login_wall、redirect_only、error、unknown |
validation_notes | ステータス理由を人が読める形で残す |
Instagramでは特に重要です。研究では、ログインページへのリダイレクトや投稿画像の欠落が示されています。生のキャプチャ数だけでは誤解を招きます。
カバレッジを可視化する
データを整えたら、可視化でレビュー優先度を判断できます。
- プラットフォーム別のキャプチャ時系列
- プラットフォーム別のステータスコード分布
- MIMEタイプ分布
- 対象ごとのユニークdigest数
- URLごとの初回・最終キャプチャ日
- プラットフォーム別の重複率
notebookではPyGWalkerでdataframeを対話的に確認できます。
import pygwalker as pyg
pyg.walk(deduped)簡単な集計表は次のように作れます。
summary = (
df.groupby("platform")
.agg(
total_captures=("original", "count"),
unique_urls=("original", "nunique"),
unique_digests=("digest", "nunique"),
first_capture=("captured_at", "min"),
last_capture=("captured_at", "max"),
)
.reset_index()
)
summary["duplicate_ratio"] = 1 - summary["unique_digests"] / summary["total_captures"]ブラウザ上で同じ流れを試すなら、Graphic Walkerが便利です。クレンジング済みデータを読み込み、タイムスタンプとプラットフォームをタイムラインに置き、ステータスコード、MIMEタイプ、digestの集計を切り替えられます。
CDXデータで証明できること、できないこと
CDXデータからは、公開URLにキャプチャがあったこと、索引化時刻、記録されたステータスコードとMIMEタイプ、同じdigestを共有する反復キャプチャを調べられます。
一方で、CDXだけでは、削除済み投稿が特定の形で存在したこと、スクリーンショットが本物であること、保存ページが全ユーザーに同じように表示されたこと、全アセットやコメントが保存されたことは証明できません。
CDXは発見と構造化に使い、証拠にはスナップショット検証を使います。
よくある失敗パターン
| 失敗パターン | 対応 |
|---|---|
200レスポンスがログイン壁だった | login_wall とラベル付けし、有効な証拠にしない |
| 重複キャプチャが多すぎる | キャプチャ数を読む前に digest を比較する |
| リダイレクトチェーン | リダイレクトのみの行は残し、遷移先を確認する |
| アセット欠落 | 画像や動画が重要ならレンダリング済みスナップショットを見る |
| ホスト名移行 | twitter.com、x.com、モバイルホスト名を明示的に追跡する |
UI中心で進めたい場合、PeekVault (opens in a new tab) はSNS URLの公開Wayback記録を検索し、CSV、JSON、HTMLでエクスポートできます。どのエクスポートも検証前の出発点として扱います。
責任ある利用
アーカイブ分析は、SNSコンテンツが変更、削除、係争化している場面など、センシティブな文脈に触れます。
次の境界を守ります。
- 公開アーカイブ記録を扱う。
- 非公開アカウントや非公開コンテンツへアクセスできるように示唆しない。
- アーカイブ記録がないことを、存在しなかった証明として扱わない。
- スナップショットを開く前に、CDX行を内容証明として扱わない。
- 出典と検証メモを残す。
- 削除要請、プライバシー、安全性に配慮する。
これは倫理面だけでなく実務面でも重要です。生の索引行と検証済み証拠を分けると、レビュー、再現、反証がしやすくなります。
FAQ
Wayback Machine CDXデータとは何ですか?
Wayback Machine CDXデータはアーカイブ索引のメタデータです。保存URL、タイムスタンプ、ステータスコード、MIMEタイプ、digest、長さを列挙します。候補スナップショットを探せますが、保存ページ本文そのものではありません。
CDXデータで削除済みSNS投稿の存在を証明できますか?
CDXだけでは証明できません。公開URLにアーカイブ記録があったことは示せますが、実際のWaybackスナップショットで必要な内容を確認する必要があります。
200ステータスコードがアーカイブ分析で失敗するのはなぜですか?
200 は成功HTTPレスポンスの記録です。ただしログイン壁、アプリシェル、リダイレクトページ、不完全なキャプチャの可能性があります。ステータスコードは絞り込み条件であり、最終証拠ではありません。
繰り返し保存されたWaybackキャプチャはどう重複排除すべきですか?
まず original と digest で同じURLの同一レスポンスを1行へまとめます。広い分析では、プラットフォーム、対象タイプ、正規化URL、digestごとの重複排除も比較します。
関連ガイド
参考資料
- Internet Archive: Wayback CDX Server API documentation (opens in a new tab)
- Bragg and Weigle: Discovering the Traces of Disinformation on Instagram in the Internet Archive (opens in a new tab)
- Kanaries: PyGWalker documentation (opens in a new tab)
- Kanaries: Graphic Walker documentation (opens in a new tab)