.wpressファイルを展開して中身を見る方法|インポート環境なしでAI解析まで

目次

.wpressとは何か

.wpress は、WordPressプラグイン「All-in-One WP Migration and Backup」がエクスポート時に出力するバックアップファイルです。サイト移行の定番プラグインなので、受け取ったことがある人も多いと思います。

扱いに困るのは、このファイルの中身を見る手段です。普通は別のWordPress環境を用意して、プラグイン経由でインポートし直します。ところが既存サイトの調査や引き継ぎで「どんなテーマやプラグインが入っているか」「DBに何が入っているか」を知りたいだけなら、インポートまでするのは大がかりすぎます。

実は .wpress は構造がとても単純な独自アーカイブで、標準では圧縮もされていません。仕組みさえ分かれば、WordPressを動かさずに展開(解凍)できます。

WordPress.org 日本語
All-in-One WP Migration and Backup 6,000万以上のサイトで信頼されています: WordPress の移行とバックアップのゴールドスタンダード。ワンクリックで WordPress サイトの移行、バックアップ、復元が可能です...

エクスポートは無料版でできる

All-in-One WP Migrationのエクスポートは、無料版で容量の制限なく使えます。

機能無料版備考
.wpress へのエクスポート可能容量制限なし
.wpress のインポート制限あり一定サイズを超えると取り込めない
クラウドへの直接エクスポート不可Google DriveやDropboxなどは有料の拡張機能が必要

制限がかかるのはインポート側です。大きなサイトの .wpress を検証環境に取り込もうとして、ここで止まるケースはよくあります。展開して中身を読むだけなら、この制限とは無関係です。

.wpressの中身と構造

アーカイブの構造

.wpress は、ファイルを順番に並べて連結しただけのアーカイブです。各ファイルの直前に、固定長 4377バイト のヘッダーが付きます。

下の図は、ヘッダーと本体の並び方と、ヘッダーの内訳を示したものです。

.wpress ファイル全体 ヘッダー 4377B ファイル本体 sizeバイト ヘッダー 4377B ファイル本体 sizeバイト … 終端ブロック NUL × 4377B ヘッダー 4377バイトの内訳 filename 255B size 14B mtime 12B path 4096B ・各フィールドは文字列。余った部分はNULで埋められる ・size と mtime も数値ではなく10進数の文字列 ・終端ブロック(全バイトNUL)が来たら読み込み終了

ヘッダーの各フィールドは次のとおりです。

フィールド位置(バイト)サイズ内容
filename0〜254255ファイル名
size255〜26814ファイル本体のサイズ(10進数の文字列)
mtime269〜28012更新日時(UNIX時刻の文字列)
path281〜43764096格納先ディレクトリのパス

つまり読み込みの手順は「4377バイト読む → size の分だけ本体を読む」の繰り返しだけです。tarをさらに単純にしたような形式だと考えると分かりやすいでしょう。

何が入っているか

展開すると、おおむね次のファイルやディレクトリが出てきます。

  • database.sql:DBのダンプ。プレーンなSQLテキストです
  • package.json:元サイトのURL、WordPress・PHP・プラグインのバージョン、エクスポート時の除外設定などのメタ情報
  • multisite.json:マルチサイトの場合のみ
  • themes/、plugins/、uploads/ など:wp-content 配下のファイル

WordPressのコアファイル(wp-admin や wp-includes)は含まれません。インポート先にWordPressが入っている前提の設計だからです。

database.sql で注意したいのは、テーブル接頭辞が SERVMASK_PREFIX_ というプレースホルダーに置き換わっている点です。wp_options は SERVMASK_PREFIX_options として記録されています。インポート時に移行先の接頭辞へ戻される仕組みなので、自分でSQLを読むときは読み替えてください。

.wpressを展開する方法

.wpress を区切りごとに分割すると、エクスポート前の個々のファイルに戻ります。

ただし、出てくるのは次のファイルだけです。

  • database.sql(DBの中身)
  • package.json(サイトURLやバージョンなどの情報)
  • wp-content 配下のファイル(テーマ、プラグイン、アップロード画像など)

wp-admin や wp-includes といったWordPress本体のファイルは、もともと .wpress に入っていないので出てきません。

Pythonで展開するスクリプト

構造が分かれば、展開処理は数十行で書けます。標準ライブラリだけで動くPythonスクリプトの例です。

import os
import sys

HEADER_SIZE = 4377  # 255 + 14 + 12 + 4096
EOF_BLOCK = b"\0" * HEADER_SIZE


def field(header, start, end):
    return header[start:end].rstrip(b"\0").decode("utf-8")


def extract(src, dst):
    dst = os.path.abspath(dst)
    with open(src, "rb") as f:
        while True:
            header = f.read(HEADER_SIZE)
            if len(header) < HEADER_SIZE or header == EOF_BLOCK:
                break

            name = field(header, 0, 255)
            size = int(field(header, 255, 269) or 0)
            path = field(header, 281, 4377)

            out = os.path.abspath(os.path.join(dst, path, name))
            if not out.startswith(dst + os.sep):
                raise ValueError(f"不正なパス: {path}/{name}")

            os.makedirs(os.path.dirname(out), exist_ok=True)
            with open(out, "wb") as o:
                remaining = size
                while remaining > 0:
                    chunk = f.read(min(1024 * 1024, remaining))
                    if not chunk:
                        raise ValueError(f"データが途中で切れています: {name}")
                    o.write(chunk)
                    remaining -= len(chunk)
            print(f"{path}/{name} ({size} bytes)")


if __name__ == "__main__":
    extract(sys.argv[1], sys.argv[2])

使い方は次のとおりです。

python3 extract_wpress.py backup.wpress ./extracted

ポイントは2つあります。

  • 本体は1MBずつ読み書きしています。数GBの .wpress でもメモリを使い切りません
  • 書き出し先が展開先ディレクトリの外に出ないか確認しています。他人から受け取ったファイルに ../ を含む細工がされていても、意図しない場所へ書き込まれるのを防げます

既存ツールを使う場合

自分で書かなくても、ServMask公式の展開ツールや、npm・Python製の非公式ツールがあります。ただ、非公式ツールはメンテナンス状況がまちまちです。中身を確認できる短いスクリプトを手元に置いておくほうが、結果的に安心です。

接頭辞を戻してSQLを読む

database.sql を実際のテーブル名で読みたい場合は、接頭辞を置換します。

sed 's/SERVMASK_PREFIX_/wp_/g' extracted/database.sql > database_wp.sql

あとはエディタで開いても、ローカルのMySQLに流し込んでも構いません。投稿データだけ確認したいなら、SERVMASK_PREFIX_posts で検索するだけでも十分なことが多いです。

インポート環境なしでAIに解析させる

従来の手順との違い

.wpress を展開できると、調査の進め方が大きく変わります。テーマやプラグインのコード、DBの中身がすべてテキストで手に入るので、AIにそのまま渡して解析させられます。

下の図は、従来の手順とAIに渡す手順を比べたものです。

従来の手順 エクスポート 環境構築 PHP・WPの版を合わせる インポート 無料版は容量制限 調査 展開してAIに渡す手順 エクスポート 展開 スクリプト1本 AIで解析 コード・設定・DBを読ませる 赤い工程(環境構築とインポート)がまるごと不要になる

一番大きいのは、環境構築が要らなくなることです。古いサイトほど、元のPHPやWordPressのバージョンに合わせた環境を用意するのに手間がかかります。無料版のインポート容量制限にも引っかかりません。

ファイル操作ができるAIなら、.wpress をそのままアップロードして「展開して中身を調べて」と頼むだけで済む場合もあります。展開処理は上のスクリプトと同じ程度の内容なので、AIが自分で書いて実行できます。

AIに任せやすい調査

展開したファイルを渡すと、たとえば次のような調査を任せられます。

  • 使っているテーマ・子テーマ・プラグインの一覧とバージョンの洗い出し
  • カスタマイズされた functions.php やテンプレートの処理内容の説明
  • package.json から元サイトのURLや動作環境を確認
  • database.sql から投稿タイプ、カスタムフィールド、オプション設定の傾向を把握
  • 古いプラグインや、更新が止まっているプラグインの洗い出し

引き継いだサイトの全体像を短時間でつかみたいときに、特に効果があります。

注意点

ファイルサイズを小さくする

uploads/ の画像や動画が含まれると、.wpress は数百MBから数GBになりがちです。AIサービスのアップロード上限を簡単に超えてしまいます。

コードとDBだけ解析したいなら、エクスポート時の詳細オプションでメディアライブラリを除外しましょう。ファイルサイズは大幅に小さくなります。

逆に、除外設定をした .wpress には当然そのデータが入っていません。テーマ、プラグイン、DBも個別に除外できるので、受け取ったファイルで何かが見当たらない場合は package.json で除外設定を確認してください。

暗号化されている場合

エクスポート時にパスワードを設定すると、ファイル本体が暗号化されます。この場合、上のスクリプトで展開しても中身は読めません。調査用には、パスワードなしでエクスポートし直してもらうのが確実です。

個人情報と機密情報

database.sql には、扱いに注意が必要なデータがそのまま入っています。

  • 会員やコメント投稿者のメールアドレスなどの個人情報
  • users テーブルのパスワードハッシュ
  • options テーブルに保存された、外部サービスのAPIキーやSMTPの認証情報
  • フォームプラグインに蓄積された問い合わせ内容

外部のAIサービスに渡してよいデータかどうかは、クライアントとの契約や社内ルールに照らして事前に判断してください。DBを渡せない場合でも、テーマとプラグインのコードだけなら問題になりにくいはずです。

静的な解析に限られる

展開して読めるのは、あくまでファイルとデータです。実際にページがどう表示されるか、どのフックがどの順で動くか、といった動作の検証はできません。

構成やコード、データの中身を把握するなら展開で十分です。動作確認や不具合の再現まで必要になったら、そのときにインポート環境を用意すれば済みます。

調査の最初の一手を「展開して読む」にするだけで、環境構築が本当に必要かどうかを先に判断できるようになります。

仕様の変更に備える

ヘッダーのフィールド長などは、プラグインのバージョンによって変わる可能性があります。展開がうまくいかない場合は、プラグイン本体の lib/vendor/servmask/archiver/ 配下にあるソースコードを確認してください。展開処理の正解はそこに書かれています。

目次