WordPress のデータを a-blog cms に移行する WXRImport プラグインを開発しました

公開日:

目次

普段 a-blog cms のサポート業務をしている中で、「WordPress から a-blog cms にデータを移したいんだけど、どうしたらいい?」というご相談をちょこちょこいただくことがあり、自分でも以前から気になっていたテーマでした。a-blog cms には標準でテキストデータの移行機能が用意されているものの、メディアファイルの引き継ぎや本文中の画像 URL の書き換えまでを一括でやってくれる仕組みはなく、「あったら便利だけど業務として組み込むほどでもないんだよなあ」とずっと頭の片隅に残っていました。

ようやく時間が取れたので個人開発で手を動かして、WordPress の WXR ファイルからエントリーもメディアも一気にインポートできる a-blog cms 拡張アプリ WXRImport として形にしました。同じところで悩んでいる方の役に立てば嬉しいなと思い GitHub で公開したので、機能の概要と使い方を紹介します。

リポジトリと配布ファイルはこちらです。

WXRImport とは

WordPress 標準のエクスポート形式である WXR(WordPress eXtended RSS)1.2 を読み込み、a-blog cms にエントリー・メディア・カテゴリー・タグをまとめてインポートする拡張アプリです。a-blog cms 標準の移行機能では扱えなかった メディアファイルの自動ダウンロードと登録 までを含めて完結させることを目的としています。

主な機能は以下のとおりです。

  • WXR ファイル(WordPress 標準エクスポート)の解析

  • エントリー(投稿・固定ページ)の一括移行

  • カスタムフィールドの引き継ぎ(フィールド名はプレフィックス wp_ を付けて保存)

  • WordPress のメディアファイルを自動でダウンロードして a-blog cms のメディアに登録

  • アイキャッチ画像を a-blog cms のメイン画像として自動設定

  • WordPress ブロック(画像・ファイル)を a-blog cms のブロック形式へ変換

  • 本文内に残った WordPress 由来のメディア URL を a-blog cms のメディア URL に自動置換

  • カテゴリー階層・タグの自動作成とマッピング

  • リアルタイムでの進捗表示と、エラー発生時の詳細ログ

  • 大量データを想定したバッチ処理

動作環境

  • a-blog cms: Ver. 3.2.20 以上

  • PHP: 8.1 以上

メディアファイルを HTTP ダウンロードする都合上、サーバーには十分なメモリと実行時間(できればメモリ 512MB 以上、max_execution_time は無制限もしくは余裕のある値)を確保しておくことをおすすめします。

インストール方法

  1. リリースページ から zip ファイルをダウンロードします。

  2. zip を解凍し、a-blog cms 設置ディレクトリの extension/plugins/ 配下に配置します。

  3. a-blog cms の管理画面 管理ページ > 拡張アプリ を開くと、一覧に WXRImport が表示されているので「インストール」をクリックします。

インストールが完了すると、管理ページに「WordPressインポート」のメニューが追加されます。

使い方

1. WordPress 側でエクスポートする

WordPress の管理画面で以下の手順を実行します。

  1. ツール > エクスポート を開く

  2. 「すべてのコンテンツ」を選択

  3. 「エクスポートファイルをダウンロード」をクリック

「投稿」だけを選んでエクスポートすると、本文中で参照されているメディア情報が含まれず取り込みが不完全になります。少し手間に感じても、必ず「すべてのコンテンツ」を選んでください。

2. a-blog cms にアップロードして移行する

a-blog cms の管理ページから「WordPressインポート」を開き、WXR ファイルをアップロードします。あわせて以下の移行オプションをチェックボックスで切り替えられます(いずれもデフォルトで 有効 です)。

  • メディアファイルを移行する

  • カテゴリーを自動作成する

  • タグを自動作成する

設定が終わったら「インポートを実行する」をクリックします。

3. 進捗の確認

移行中は進捗バーと処理ログがリアルタイムで表示され、完了すると「インポートが完了しました。」のアラートと、処理されたエントリー・メディアの一覧が画面に残ります。途中でエラーが発生した場合は、どのエントリー・どのメディアで失敗したかが処理ログに残るため、原因の特定がしやすくなっています。

移行されるデータと挙動

移行先のブログは「現在ログインしているブログ」になります。あわせて、いくつか覚えておいていただきたい仕様があります。

  • 全エントリーの投稿者は実行ユーザーになります(WordPress 側の投稿者は引き継がれません)

  • WordPress のパスワード保護設定は無視されます

  • WordPress のカテゴリー階層は維持されます

  • アイキャッチ画像は a-blog cms のメイン画像として引き継がれます

  • Yoast SEO のメタ情報(タイトル・ディスクリプション)も引き継がれます

  • 本文中の画像・ファイルブロックは a-blog cms のブロック形式へ変換され、それ以外のブロックは HTML としてそのまま保存されます

自動付与されるカスタムフィールド

移行されたエントリーには、WordPress 側の情報を後から参照できるよう以下のフィールドが自動付与されます。

フィールド名

内容

wp_post_id

WordPress の投稿 ID

wp_guid

WordPress の GUID

wp_post_type

WordPress の投稿タイプ(post / page など)

wp_featured_media_id

アイキャッチ画像の投稿 ID(設定がある場合のみ)

また、WordPress 側で設定されていたカスタムフィールドは、フィールド名の先頭に wp_ を付けた名前で保存されます(例: featured_imagewp_featured_image)。wp_post_id をキーに WordPress 側のデータと突き合わせる、といった運用が可能です。

再実行時の注意

  • 同じ WXR ファイルを再度インポートすると、エントリーコードが既存と重複しないように自動で連番(_1_2 …)が付与され、新しいエントリーとして作成されます。既存エントリーは上書きされません。

  • メディアとカテゴリーは既存のものがあれば再利用されます

  • 移行処理中は、同じブログで別の移行を同時に開始できません(ロックがかかります)

Tips: メディアを HTTP ダウンロードせずに移行する

移行元の WordPress サイトがすでに停止している、あるいは大量のメディアをネットワーク越しに取得すると現実的でない、というケースがあります。WXRImport では WXR ファイル内のメディア URL をローカルパスに書き換えておくと、HTTP ダウンロードではなくサーバー上のファイルから直接コピーしてメディアを登録する という挙動をサポートしています。

ただし、LFI(Local File Inclusion)対策のため、ローカルパスから取り込めるのは WXR_IMPORT_LOCAL_PATH_BASE で指定したディレクトリ配下のファイルのみ に制限されています。デフォルトは archives/wxr-import/source/(プラグイン専用の取り込み置き場)です。

パターン A: デフォルトの取り込み専用ディレクトリを使う

.env の追記は不要です。

  1. WordPress の wp-content/uploads/ 一式を、a-blog cms 設置サーバの archives/wxr-import/source/ 配下にコピーします。

    archives/wxr-import/source/
    └── wp-content/
        └── uploads/
            └── 2026/01/sample.png
  2. WXR ファイル(XML)内のメディア URL を、archives/wxr-import/source/ を含むパスへ一括置換します。

    https://example.com/wp-content/uploads/
        → /archives/wxr-import/source/wp-content/uploads/
  3. 書き換えた WXR ファイルをアップロードして移行を実行します。

パターン B: 既存ディレクトリを取り込み元に指定する

すでにサーバ上の任意のディレクトリへ wp-content/uploads/ を配置している場合は、.envWXR_IMPORT_LOCAL_PATH_BASE をそのディレクトリ(または上位ディレクトリ)に合わせます。

  1. .env に次の設定を追加します。

    WXR_IMPORT_LOCAL_PATH_BASE=/var/www/html/
  2. WXR ファイル内の URL を、ドキュメントルート相対パスへ置換します。

    https://example.com/wp-content/uploads/  →  /wp-content/uploads/
  3. 書き換えた WXR ファイルをアップロードして移行を実行します。

共通の注意点

  • <wp:attachment_url> だけでなく、本文中のメディア URL もすべて置換してください。

  • 受け入れられるパス形式は、WXR_IMPORT_LOCAL_PATH_BASE 配下に解決される限り次のいずれでも構いません。

    • ドキュメントルート相対パス(例: /path/to/sample.png

    • 絶対パス(例: /var/www/html/path/to/sample.png

    • file:// URL(例: file:///var/www/html/path/to/sample.png

  • 公開ディレクトリ配下にアップロードファイルを置く場合は、a-blog cms の管理画面以外からアクセスできないようアクセス制御に注意してください。

.env で調整できる主な設定

WXRImport の挙動は .env で細かくチューニングできます。すべてのキーは省略可能で、省略時には安全側のデフォルトが適用されます。

キー

意味

デフォルト

WXR_IMPORT_LOCAL_PATH_BASE

ローカル取り込みの許可ベース

archives/wxr-import/source/

WXR_IMPORT_ALLOWED_PRIVATE_HOSTS

開発環境用に許可するプライベートホスト名

空(厳格にブロック)

WXR_IMPORT_MAX_FILE_SIZE

メディアファイル 1 個あたりの最大サイズ(バイト)

52428800(50MB)

WXR_IMPORT_DOWNLOAD_DELAY_MICROSECONDS

同一ドメインへの連続ダウンロード間隔

500000(0.5 秒)

WXR_IMPORT_BATCH_PAUSE_MICROSECONDS

エントリーバッチ間の追加ポーズ

0(無効)

WXR_IMPORT_DEFAULT_BATCH_SIZE

管理画面でバッチサイズを未入力にしたときの既定値

50

WXR_IMPORT_ALLOWED_PRIVATE_HOSTS は SSRF(Server Side Request Forgery)対策を一部緩める設定なので、本番環境では空欄のままにしてください。host.docker.internal のようなプライベートホストから WordPress サイトを取り込みたい開発環境でのみ設定する想定です。

トラブルシューティング

開発中によく踏みやすかったポイントを置いておきます。

メディアのダウンロードに失敗する

  • WordPress サイトが稼働中で、メディア URL に到達できるかをまず確認してください

  • URL の形式が https://example.com/wp-content/uploads/... のように正規化されているか確認してください

  • 移行元がすでに停止している場合は、前述のローカル取り込みパターンに切り替えてください

メモリ不足エラーが発生する

  • .envWXR_IMPORT_DEFAULT_BATCH_SIZE を 10〜20 件程度まで小さくする(デフォルトは 50 件)

  • PHP の memory_limit を増やす

  • 一度に全件移行せず、カテゴリーや期間で分割しながら移行する

処理が途中で停止する

  • PHP の max_execution_time を確認する

  • サーバーの CPU・メモリ・ディスク使用率を確認する

  • WXRImport の詳細ログで、どのエントリー・どのメディアまで進んだかを確認する

まとめ

WXRImport を使うと、WordPress から a-blog cms への移行で一番手間のかかる「エントリー本文と、本文に紐づくメディアを矛盾なく移す」という作業をまるっと自動化できます。「a-blog cms に移したいけれど、WordPress のデータをどうやって持ってくるか悩ましい」と感じている方の手助けになれば嬉しいです。

不具合のご報告や機能のご要望は GitHub の Issue でお待ちしております。