WordPressの記事が消える前にやった1つのこと

※この記事にはアフィリエイトリンクを含みます。

WordPress記事はMarkdown+GitHubで守れる

結論から言います。

WordPressの記事は『XMLエクスポート → Markdown変換 → GitHub管理』の3ステップで守れます。

サーバーが飛んでも、サービスが終了しても、手元とGitHubに記事が残る状態を作れます。

一度仕組みを作ってしまえば、あとは月1回の作業だけです。

「記事が全部消えたら」と思った日

WordPressでブログを続けていると、ふと気づく瞬間があります。

「この記事、全部サーバーの中にしかないな」と。

自分の場合、記事がそこそこ増えてきたタイミングでした。ふとサーバー障害のニュースを見て、「もしこのサーバーが止まったら、何も残らないのでは」と思ったんです。

WordPressの記事データは、サーバー上のデータベースに保存されています。つまり、サーバーが壊れたり、サービスが終了したりすれば、長年書いてきた記事が一瞬で消える可能性がある。

これは推測でも脅しでもなく、仕組みとしてそうなっています。

で、実際にバックアップの仕組みを調べてみると、意外とシンプルな方法で解決できました。それが今回の話です。

WordPressだけに記事を置くリスク

WordPressで記事を管理するとき、多くの人はサーバー上のデータベースだけに記事を預けている状態になっています。

この構造には、いくつかリスクがあります。

  • サーバー障害で記事データが消える可能性がある
  • レンタルサーバー会社がサービスを終了する可能性がある
  • バックアップ用プラグインが正常に動いているかどうか、実は確認していない人が多い
  • REST APIで自動取得しようとしても、サーバーやプラグインの設定で使えないケースがある

要は、『サーバーに全部任せている』状態は、思っている以上に脆いということです。

「バックアップしてるつもり」と「復元できる状態」は別物です。

バックアップを先送りにする人の共通点

バックアップをやらない人には、だいたい共通するパターンがあります。

1つ目。『プラグインで自動バックアップしてるから大丈夫』と思っている。でも、そのプラグインのバックアップ先がサーバー内だったりすると、サーバーごと消えます。

2つ目。『バックアップの存在は知ってるけど、一度も復元テストをしたことがない』。バックアップは取れていても、いざというとき復元できるかどうかは試してみないとわからないです。

3つ目。『まだ記事が少ないし』と後回しにしている。でも、記事が増えてからやろうとすると、面倒になってさらに後回しになる。結局やらないまま時間が経つパターンです。

4つ目。『サーバー会社がバックアップしてくれている』と信じている。会社によってはバックアップしてくれますが、保持期間や復元の条件は会社ごとに違います。全部戻る保証はないです。

考え直す
バックアップ、「やってるつもり」で止まっていないか考え直してみてください。
・あなたの記事、今サーバーが消えたら何本手元に残りますか?

やること:3ステップで記事をGitHubに逃がす

今日やることは1つだけ。まず『STEP 1のXMLエクスポート』をやってみてください。

まずは1つやってみる
・WordPress管理画面の「ツール → エクスポート」からXMLファイルを1回ダウンロードする

全体の流れは3ステップです。

STEP 1:WordPressからXMLをエクスポートする

WordPressには記事を丸ごとエクスポートする機能が標準で付いています。

  1. WordPress管理画面にログイン
  2. 「ツール → エクスポート」にアクセス
  3. 「すべてのコンテンツ」を選択
  4. 「エクスポートファイルをダウンロード」をクリック

これで WordPress.2026-04-05.xml のような名前のファイルがダウンロードされます。このファイルを ~/ai-blog/ フォルダに置いておきます。

STEP 2:PythonでXMLをMarkdownに変換する

エクスポートしたXMLファイルを、Pythonスクリプトで一括変換します。

まずライブラリをインストールします。

pip3 install html2text

次に、以下のスクリプトを ~/ai-blog/scripts/xml_to_markdown.py として保存します。

#!/usr/bin/env python3
import os
import re
import xml.etree.ElementTree as ET
from datetime import datetime
import html2text

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
XML_FILE = os.path.join(BASE_DIR, "WordPress.2026-04-05.xml")

NAMESPACES = {
"content": "http://purl.org/rss/1.0/modules/content/",
"wp": "http://wordpress.org/export/1.2/",
"dc": "http://purl.org/dc/elements/1.1/",
}

def html_to_markdown(html):
converter = html2text.HTML2Text()
converter.ignore_links = False
converter.ignore_images = False
converter.body_width = 0
return converter.handle(html).strip()

def parse_posts(xml_file):
tree = ET.parse(xml_file)
root = tree.getroot()
posts = []
for item in root.iter("item"):
post_type = item.find("wp:post_type", NAMESPACES)
if post_type is None or post_type.text != "post":
continue
posts.append({
"title": item.findtext("title") or "",
"link": item.findtext("link") or "",
"date": item.findtext("wp:post_date", namespaces=NAMESPACES) or "",
"status": item.findtext("wp:status", namespaces=NAMESPACES) or "",
"content": item.findtext("content:encoded", namespaces=NAMESPACES) or "",
})
return posts

def save_post(post, index):
try:
dt = datetime.strptime(post["date"], "%Y-%m-%d %H:%M:%S")
except Exception:
dt = datetime.now()

title_for_filename = re.sub(r'[/\\:*?"<>|]', "", post["title"]).strip() or f"post-{index}"
filename = f"{dt.strftime('%Y-%m-%d')}-{title_for_filename}.md"
save_dir = os.path.join(BASE_DIR, "posts", dt.strftime("%Y"), dt.strftime("%m"))
os.makedirs(save_dir, exist_ok=True)

body = html_to_markdown(post["content"]) if post["content"] else ""
md = f"""---
title: "{post['title'].replace('"', "'")}"
date: {dt.strftime('%Y-%m-%d')}
status: {post['status']}
original_url: {post['link']}
---

# {post['title']}

{body}
"""
with open(os.path.join(save_dir, filename), "w", encoding="utf-8") as f:
f.write(md)

def main():
posts = parse_posts(XML_FILE)
print(f"{len(posts)}件の記事を変換します...")
for i, post in enumerate(posts, 1):
save_post(post, i)
print(f" [{i}/{len(posts)}] {post['title'][:45]}")
print("完了!")

if __name__ == "__main__":
main()

実行します。

python3 ~/ai-blog/scripts/xml_to_markdown.py

実行すると posts/年/月/ フォルダに記事がMarkdownファイルとして保存されます。

posts/
└── 2024/
├── 08/
│ ├── 2024-08-06-ブログを立ち上げた理由.md
│ └── 2024-08-08-WordPressの自作プラグイン.md
└── 09/
└── ...

ファイル名がそのまま記事タイトルになるので、一目で内容がわかります。

STEP 3:GitHubにアップロードして管理する

GitHubにリポジトリを作って、変換した記事をpushします。

  1. GitHubで新規リポジトリを作成(Private推奨)
  2. 以下のコマンドで初期化&push
cd ~/ai-blog
git init
git add .
git commit -m "初回コミット: WordPress記事をMarkdown化"
git remote add origin https://github.com/ユーザー名/my-blog.git
git branch -M main
git push -u origin main

これで記事がGitHubに保存されます。年月フォルダごとに整理された状態で見られます。

月1回のバックアップ運用

仕組みができたら、あとは月1回この手順を繰り返すだけです。

# 1. WordPressからXMLをエクスポートして ai-blog/ に置く
# 2. 変換スクリプトを実行
python3 ~/ai-blog/scripts/xml_to_markdown.py

# 3. GitHubにpush
cd ~/ai-blog
git add .
git commit -m "月次バックアップ"
git push

慣れれば5分で終わります。

補足:REST APIが使えない場合

WordPressのREST APIを使って自動取得しようとすると、サーバーやプラグインの設定によって動かないことがあります。

今回のようにXMLエクスポートを使う方法なら、サーバー設定やプラグインの影響を受けずに確実に記事を取り出せます。

念のため補足しておくと、REST APIが使える環境なら自動化の選択肢も広がりますが、『まず確実にバックアップを取る』ことが先です。

記事を守ったら次は増やす番

バックアップの仕組みが整うと、ブログ運営の安心感が変わります。

「消えるかも」という不安がなくなるだけで、記事を書くことに集中しやすくなる。

仕組みを1回作ったら、次はその記事を読者に届ける導線のほうに目を向けてみてください。

月1回の習慣で記事は守れる

WordPressの記事は、サーバー上のデータベースにだけ預けている状態だと脆いです。

でも、XMLエクスポート → Markdown変換 → GitHub管理の3ステップを月1回やるだけで、記事はローカルとGitHubの両方に残ります。

仕組みは一度作れば終わり。あとは月1回の習慣にするだけです。

まずは今日、XMLエクスポートを1回やってみてください。

おすすめの記事