MENU

WordPressリビジョンをAPIで比較する

当ページのリンクには広告(PR)が含まれていることがあります。
WordPressリビジョンをAPIで比較する。過去の投稿本文、版を取得、更新前後を比較の処理例。

記事の更新履歴が残っていても、何を直したのかまで一覧から分かるとは限りません。WordPressのリビジョンは過去のタイトルや本文を確認するための記録です。REST APIで2件のリビジョンを取得し、本文の差分を手元で読むと、公開中の内容を変えずに変更箇所を調べられます。

ここでは、架空の記事IDが42、比べたいリビジョンIDが101と108という例を使います。Pythonの処理は保存したJSONの比較だけで、WordPressへの復元・更新・削除は行いません。

目次

投稿IDとリビジョンID

リビジョンの一覧は元の投稿IDを使う/wp-json/wp/v2/posts/42/revisionsで取得します。個別の記録なら、末尾にリビジョンIDを付けます。

GET /wp-json/wp/v2/posts/42/revisions/101?context=edit
GET /wp-json/wp/v2/posts/42/revisions/108?context=edit

context=editは編集用のデータを求める指定です。認証と対象記事を編集できる権限が必要になります。自分が管理するサイトで、許可されたアプリケーションパスワードなどを使って取得してください。URLだけ分かれば、他人の記事の履歴も読めるという仕組みではありません。

一覧の返却順だけで「前」と「後」を決めず、ID、日時、parentを見ます。parentは元の投稿のIDです。一覧を全部取得する必要がある場合は、ページ分割も確認します。表示された最初の数件が履歴の全件とは限りません。

保存した本文を比較するコード

取得結果をold.jsonとnew.jsonに保存します。本文は表示用のrenderedではなく、編集用のcontent.rawで比べます。表示用のHTMLには、テーマやフィルターによる変換が入ることがあるためです。

import difflib
import json
from pathlib import Path

def revision_text(item, expected_parent):
    if item.get("parent") != expected_parent:
        raise ValueError("別の記事のリビジョンです")
    content = item.get("content", {})
    text = content.get("raw")
    if not isinstance(text, str):
        raise ValueError("content.rawを取得し直してください")
    return text

def compare_revisions(before, after, parent):
    if before.get("id") == after.get("id"):
        raise ValueError("同じリビジョンが選ばれています")
    left = revision_text(before, parent)
    right = revision_text(after, parent)
    lines = difflib.unified_diff(
        left.splitlines(keepends=True),
        right.splitlines(keepends=True),
        fromfile="before", tofile="after",
    )
    return "".join(
        line if line.endswith("\n") else
        line + "\n\\ No newline at end of file\n"
        for line in lines
    )

if __name__ == "__main__":
    before = json.loads(Path("old.json").read_text(encoding="utf-8"))
    after = json.loads(Path("new.json").read_text(encoding="utf-8"))
    print(compare_revisions(before, after, 42))

たとえば元の本文が<p>締切は月曜です。</p>、更新後が<p>締切は火曜です。</p>なら、前の行には-、後の行には+が付きます。元の行末に改行がない場合は、表示用の改行とNo newline at end of fileという注記を添えます。保存した本文そのものは変更しません。記号を見て変更箇所を探し、日付や条件の変更が意図どおりかを読みます。長い段落が1行に保存されていると、その段落全体が差分になる点も押さえてください。

差分が出ない場合の確認

同じIDを2回保存していないか、本文以外の項目だけが変わったのかを確認します。タイトルも比較したいなら、本文とは別にtitle.rawを照合します。JSON全体の文字列比較だけでは取得時の書式差まで変更として数えてしまいます。

改行コードだけが違う場合も、差分に現れることがあります。差分を消そうとして本文を一律に整形すると、コードブロックの空白や改行まで変えるおそれがあります。最初は取得した状態を残し、何の差だったかを確認する順番が扱いやすいです。

リビジョンはサイトの設定によって保持件数が変わります。画像ファイルやプラグイン設定を含むサイト全体のバックアップでもありません。必要な履歴が見つからない場合は、取得範囲と保持設定を確認し、更新前に別途保存した控えがあるか調べます。差分の確認を終えても、このコードが記事を元に戻すことはありません。

関連する記事

WordPressリライト履歴の残し方|更新日だけ変えない運用

WordPressバックアップの基本|API運用前に守るべきこと

公式資料

Post Revisions – REST API Handbook | Developer.WordPress.org

Posts – REST API Handbook | Developer.WordPress.org

この記事を書いた人

Watanabeのアバター Watanabe サイト運営者

2020年よりブログ開始。
SEOが思いのほか性にあっていたようで現在に至る。
モットーは「勝率の高い選択をする」
AIは活用するが吉、最後は人間が息を吹き込む。
アートと科学を追求し、日々精進。
―――
収益:6~7桁をウゴウゴ。
サイト:ペラサイト~中規模サイトまで運営中。
案件:1000円以上の案件をメインに取組中。
打ち手:ブラックSEO~ホワイトSEOまで
―――

目次