
はじめに
前回の記事では、AIが生成したブログ下書きをそのまま使わず、品質チェックする仕組みについて書いた。
筆者のブログ自動化ツールでは、承認済みテーマから記事構成案を作り、OpenAI APIで本文下書きを生成し、その後に品質チェックを行う。
ここまで来ると、次にやりたくなるのがWordPressへの登録である。
手元のMarkdownファイルとして下書きが作れても、毎回WordPress管理画面を開き、タイトルを入れ、本文を貼り付け、下書き保存するのは手間である。
そこで筆者は、WordPress REST APIを使って、品質チェック済みの記事だけをWordPressへ下書き登録する仕組みを作った。
ただし、ここでも重要なのは、自動公開はしないということである。
今回の仕組みでは、WordPressへ送信する場合でも、投稿ステータスは必ず draft にする。公開はWordPress管理画面で人間が最終確認してから行う。
記事下書き生成
↓
品質チェック
↓
wordpress_ready を確認
↓
WordPressへ draft 登録
↓
人間が管理画面で確認
↓
公開
本記事では、WordPress下書き登録機能をどのように作ったか、そしてなぜ自動公開しない設計にしたのかを紹介する。
WordPressに送る対象を絞る
最初に決めたのは、すべての下書きをWordPressへ送らないことである。
前工程の品質チェックでは、記事ごとに wordpress_ready を出力するようにしている。
wordpress_ready = yes
wordpress_ready = after_revision
wordpress_ready = no
WordPress下書き登録の対象にするのは、原則として yes または after_revision のものだけである。
yes
→ WordPress下書き登録候補
after_revision
→ 修正前提で下書き登録してもよい候補
no
→ 登録しない
この条件を入れないと、品質チェックで問題ありと判定された記事までWordPressに流れてしまう。
AI記事生成では、生成できたことと、投稿してよいことは別である。
そこで、WordPress投稿処理では outputs/draft_review_summary.csv を読み込み、wordpress_ready を見て対象記事を絞るようにした。
dry-runをデフォルトに
WordPress連携で特に重要なのは、いきなり投稿しないことである。
今回の仕組みでは、dry-runとexecuteを分けた。
python scripts/post_wordpress_drafts.py --limit 1 --dry-run
dry-runでは、WordPress APIには送信しない。
送信予定の記事タイトル、本文、対象ファイル、投稿ステータスなどを確認するだけである。
実際にWordPressへ送る場合は、明示的に --execute を付ける。
python scripts/post_wordpress_drafts.py --limit 1 --execute
この設計にした理由は、事故を防ぐためである。
自動化ツールでは、実行した瞬間に外部サービスへ反映される処理が一番怖い。
WordPress投稿もその一つである。
dry-runを挟むことで、送信前に確認できる。
投稿ステータスは必ずdraftにする
今回の仕組みでは、WordPressに投稿する場合でも、ステータスは必ず draft に固定した。
status = draft
publish は実装しない。
これはかなり重要である。
AIが生成した記事は、品質チェックを通っていても、まだ人間の最終確認が必要である。
確認すべき項目は多い。
- タイトルは自然か
- 本文に誤情報がないか
- 見出し構成は読みやすいか
- 公式確認が必要な箇所は残っていないか
- 内部リンクは正しいか
- アイキャッチ画像は適切か
- カテゴリとタグは合っているか
- MarkdownからHTMLへの変換が崩れていないか
これらを確認せずに公開するのは危険である。
そのため、今回の仕組みでは、WordPressへの登録はあくまで下書き作成までにした。
AIとPythonは下書き置き場まで運ぶ係である。
公開ボタンを押す係ではない。
WordPress Application Passwordを使う
WordPress REST APIで認証付きの操作を行うために、Application Passwordを使った。
.env には、以下のような設定を入れる。
WORDPRESS_BASE_URL=https://syanaise3wariup.com
WORDPRESS_USERNAME=your_wordpress_username
WORDPRESS_APPLICATION_PASSWORD="your_application_password"
ここで注意が必要なのは、WORDPRESS_APPLICATION_PASSWORD に入れるのはWordPressの通常ログインパスワードではないという点である。
WordPressのプロフィール画面で発行する、アプリケーションパスワードを使う。
また、これらの値は .env に入れ、GitHubには上げない。
.env.example にはダミー値だけを書く。
WORDPRESS_BASE_URL=https://example.com
WORDPRESS_USERNAME=your_wordpress_username
WORDPRESS_APPLICATION_PASSWORD=your_wordpress_application_password
WordPress下書き登録機能では、OpenAI APIキーやGoogle OAuth情報と同じく、秘密情報の扱いが重要になる。
動けばよいではなく、漏れないように動かす必要がある。
MarkdownをHTMLに変換して投稿する
本文下書きはMarkdownで保存している。
一方、WordPress REST APIへ投稿する本文は、HTMLとして送る方が扱いやすい。
そのため、投稿処理ではMarkdownをHTMLに変換してから送信するようにした。
流れは以下である。
outputs/article_drafts/*.md
↓
front matterを読み取る
↓
title / description / action を取得
↓
Markdown本文をHTMLに変換
↓
WordPress REST APIへPOST
front matterには、たとえば以下のような情報を入れている。
---
title: Teamsで添付ファイルが開けない時の原因と確認ポイント
description: Teamsで添付ファイルが開けない時の確認ポイントを社内SE向けに整理する。
action: create_new_article
review_status: draft
---
この情報を使って、WordPress投稿時のタイトルや本文を組み立てる。
タイトルがfront matterにない場合は、Markdown内の最初のH1を使うようにした。
このようにしておくと、本文生成からWordPress下書き登録までの流れがつながりやすい。
二重投稿を防ぐ
WordPress投稿機能で気を付けたのが、同じ記事を何度も投稿してしまう問題である。
テスト中は、同じコマンドを何度も実行することがある。
そのたびに同じタイトルの下書きが増えると、WordPressの投稿一覧が下書きの群生地になる。
そこで、投稿結果をCSVに記録するようにした。
outputs/wordpress_post_results.csv
outputs/wordpress_post_report.md
投稿済みのファイルやタイトルを記録し、重複投稿を避ける設計にした。
完全ではないが、少なくとも同じ下書きを何度も送る事故は減らせる。
自動化ツールでは、成功時の結果を記録しておくことが重要である。
あとから「何を送ったか」が分からなくなると、調査が面倒になる。
REST APIのURL形式で詰まった
WordPress REST API連携では、いくつかのエラーに遭遇した。
その一つが、REST APIのURL形式である。
最初は、以下の形式で投稿しようとしていた。
https://syanaise3wariup.com/wp-json/wp/v2/posts
しかし、環境によっては404が返ることがあった。
そこで、?rest_route= 形式にも対応させた。
https://syanaise3wariup.com/?rest_route=/wp/v2/posts
今回の環境では、最終的に rest_route 形式を使うことで通るようになった。
.env では、以下のように設定できるようにした。
WORDPRESS_REST_API_MODE=rest_route
また、自動判定用に auto も使える設計にした。
WORDPRESS_REST_API_MODE=auto
WordPress REST APIは、環境やパーマリンク設定、サーバー設定によって挙動が変わることがある。
そのため、URL形式を固定せず、設定で切り替えられるようにしておくと安心である。
Application Password認証でも詰まった
次に詰まったのが、Application Password認証である。
/wp/v2/users/me にアクセスしても、401が返る状態になった。
ユーザー名やApplication Passwordは確認しても合っているように見える。
このとき疑ったのが、AuthorizationヘッダーがWordPressまで届いていない問題である。
最終的には、WordPressのパーマリンク設定を見直すことで認証が通るようになった。
このあたりは、WordPress REST API連携でかなり詰まりやすいポイントである。
確認すべき項目は以下である。
- WordPressのユーザー名が正しいか
- 通常パスワードではなくApplication Passwordを使っているか
- Application Passwordの空白や改行が混ざっていないか
- パーマリンク設定が適切か
- AuthorizationヘッダーがPHP/WordPressへ届いているか
- セキュリティプラグインがREST APIを制限していないか
WordPress REST APIの認証エラーは、単純なパスワード間違いとは限らない。
サーバー設定やパーマリンク設定が絡むこともある。
実記事だけ403になる問題もあった
認証が通り、最小テスト投稿も成功したあと、実際の記事下書きを投稿すると403になる問題が起きた。
これはかなり悩ましい。
なぜなら、テスト投稿は通るからである。
つまり、REST APIも認証も成功している。
それなのに実記事だけ403になる。
この場合、原因として考えられるのは、本文の中身がWAFに引っかかっていることである。
技術記事には、次のような要素が含まれることがある。
- PowerShellコマンド
- Pythonコード
- Windowsパス
- JSON
- YAML
- HTMLタグ
- URL
- コードブロック
これらが、サーバー側のWAFに攻撃っぽく見えることがある。
実際、最小本文では投稿できるが、コードブロックを含む実記事では403になるという状況があった。
そこで、投稿方式や本文の安全化を設定で変えられるようにした。
form送信とWAF安全モードを追加した
WAF対策として、まず送信形式を切り替えられるようにした。
WORDPRESS_POST_BODY_MODE=form
JSON送信ではなく、フォーム送信に切り替えることで通る場合がある。
また、WAF安全モードも追加した。
WORDPRESS_WAF_SAFE_MODE=true
WAF安全モードでは、WordPressに送る本文に対して以下のような処理を行う。
- コードブロックを一時的にプレースホルダー化する
- 長いコマンド列をそのまま送らない
- 危険視されやすいHTMLタグを除去する
- 本文末尾に、詳細コマンドは管理画面で確認・追記する旨を入れる
元のMarkdownファイルは変更しない。
WordPressへ送るpayloadだけを安全化する。
これにより、WAFに弾かれやすい記事でも、下書き登録できる可能性が上がる。
もちろん、WAF安全モードを使った場合は、WordPress管理画面で本文を確認し、必要に応じてコードブロックを手動で整える必要がある。
自動化は便利だが、WAFと戦う場合は人間の確認も欠かせない。
Codexには何を作らせたか
このWordPress下書き登録機能も、Codexに段階的に作らせた。
最初から「WordPressに投稿する機能を作って」とだけ頼んだわけではない。
依頼した内容は、ざっくり言えば以下である。
draft_review_summary.csv を読み込む
wordpress_ready の記事だけ対象にする
Markdown下書きを読み込む
front matterからタイトルなどを取得する
MarkdownをHTMLへ変換する
WordPress REST APIへ status=draft で投稿する
dry-runとexecuteを分ける
投稿結果をCSVとMarkdownレポートに保存する
REST API URL形式を切り替えられるようにする
form送信とWAF安全モードに対応する
ポイントは、公開処理を作らせなかったことである。
Codexには、下書き登録までを明確に指示した。
自動公開はしない
status は必ず draft
publish は実装しない
この制約を最初から入れておくことで、危険な実装を避けやすくなる。
実行の流れ
現在の実行イメージは以下である。
まずdry-runで確認する。
python scripts/post_wordpress_drafts.py --limit 1 --dry-run
問題なければ、1件だけexecuteする。
python scripts/post_wordpress_drafts.py --limit 1 --execute
REST APIの形式やWAF対策を指定する場合は、.env で設定する。
WORDPRESS_REST_API_MODE=rest_route
WORDPRESS_POST_BODY_MODE=form
WORDPRESS_WAF_SAFE_MODE=true
最初から複数件を送らない。
まずは1件だけ送る。
WordPress側で下書きとして登録されたことを確認し、本文や表示を確認する。
この「1件だけ試す」運用はかなり重要である。
自動化では、大量処理できることより、少量で安全に確認できることの方が先である。
下書き登録後に確認すること
WordPressに下書き登録できたら、管理画面で以下を確認する。
- 投稿ステータスが下書きになっているか
- タイトルが意図通りか
- 本文の見出し構成が崩れていないか
- コードブロックが崩れていないか
- 内部リンクが正しいか
- アイキャッチ画像を設定するか
- カテゴリとタグが適切か
- 要公式確認の箇所が残っていないか
下書き登録はゴールではない。
WordPress管理画面で確認するための準備である。
ここを勘違いすると、AI自動化が危険なものになる。
実装して感じたこと
WordPress下書き登録を実装して感じたのは、外部サービス連携は最後の数メートルが一番ぬかるむということである。
Search Console API取得、記事構成案生成、本文生成、品質チェックまではローカル中心の処理である。
しかし、WordPress投稿は外部サービスに書き込む処理である。
そこには、認証、権限、パーマリンク、WAF、サーバー設定、REST APIの形式などが絡む。
実際、以下のような問題に遭遇した。
401
403
404
WAF
rest_route
Application Password
Authorizationヘッダー
このあたりは、単にコードを書くだけでは解決しにくい。
サーバー側の設定やWordPress側の仕様も関係する。
だからこそ、dry-run、status=draft固定、1件ずつ実行、ログ出力が重要である。
自動公開しない設計にしてよかった
実際にWordPress連携でエラーに遭遇して、あらためて自動公開しない設計にしてよかったと感じた。
もし最初から自動公開まで実装していたら、エラー対応だけでなく、公開事故のリスクも抱えることになっていた。
下書き登録までなら、失敗しても影響は限定的である。
成功しても、管理画面で確認してから公開できる。
AIとWordPressをつなぐ場合、最初に実装するべきなのは自動公開ではない。
安全な下書き登録である。
この順番はかなり大事である。
まとめ
筆者は、品質チェック済みのAI生成記事を、WordPress REST APIで下書き登録する仕組みを作った。
ただし、自動公開はしない。
WordPressへの投稿ステータスは必ず draft とし、公開は人間が管理画面で最終確認してから行う。
実装では、Application Password認証、dry-run、executeの分離、MarkdownからHTMLへの変換、投稿結果ログ、REST API URL形式の切り替え、WAF対策などを入れた。
特に重要なのは、WordPressへ送る対象を品質チェック済みに限定することである。
AIが生成した記事をそのまま公開するのではなく、下書きとして運び、人間が確認してから公開する。
この設計にすることで、AIによる効率化と安全なブログ運用のバランスを取りやすくなる。
次回は、WordPress REST API連携で実際に詰まった401、403、404エラーと、その対処について詳しく紹介する予定である。


コメント