こんにちは、Juntechです。
最近、自動化ブログを謳っておきながらWordPressの管理画面をポチポチしてるのが哀しくなってきました。

ということでここ数週間で、APIを使ったWordPressの投稿自動化に挑戦してみたいと思います。

今回はまずWordPress APIを触ってみます。

APIについてはこちら

【用語解説】APIってなに?【使ってみよう】

プラグイン導入・設定

まずはAPIを使うためのプラグインを導入・設定していきます。

WP REST APIプラグイン

WordPressでAPIを使うプラグインです。
https://ja.wp-api.org/

まずはリンク先からzipをダウンロードします。

WordPressの管理画面に入って「プラグイン」 -> 「新規追加」 へ進み、
「プラグインをアップロード」を選択します。

「ファイルを選択」で先ほどダウンロードしたzipを選択し、
「今すぐインストール」します。

インストールが終わったら、「プラグインを有効化」します。

これでAPIが使えるようになります。

Application Passwordsプラグイン

次はAPIを使うときの認証プラグインを導入します。

Application Passwords

「プラグイン」->「新規追加」 で、キーワード「Application Passwords」で検索し、
Application Passwordsを「今すぐインストール」します。

インストールが終わったら、「有効化」します。

パスワードを生成

インストールした「Application Passwords」を使って、
APIパスワードを生成します。

「ユーザー」->「ユーザー一覧」へ進みます。

ユーザ名をクリックし、プロフィール画面へ進みます。

スクロールしていくと、Application Passwordsの項目があります。
が、、エラーが出ていますね。。

リンク先を読んでみると、.htaccessを修正する必要があるっぽいです。

ということで、WPサーバに入って.htaccessを修正します。

$ ssh autohacks
$ cd ~/autohacks.net/public_html
$ vi .htaccess

修正前

SetEnvIf Request_URI ".*" Ngx_Cache_NoCacheMode=off
SetEnvIf Request_URI ".*" Ngx_Cache_StaticMode

Satisfy Any

# BEGIN WordPress
# `BEGIN WordPress` から `END WordPress` までのディレクティブ (行) は
# 動的に生成され、WordPress フィルターによってのみ修正が可能です。
# これらのマーカー間にあるディレクティブへのいかなる変更も上書きされてしまいます。
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>

# END WordPress

下記一行を、RewriteEngine Onの後に挿入します。

RewriteRule .* - [E=REMOTE_USER:%{HTTP:Authorization}]

修正後

SetEnvIf Request_URI ".*" Ngx_Cache_NoCacheMode=off
SetEnvIf Request_URI ".*" Ngx_Cache_StaticMode

Satisfy Any

# BEGIN WordPress
# `BEGIN WordPress` から `END WordPress` までのディレクティブ (行) は
# 動的に生成され、WordPress フィルターによってのみ修正が可能です。
# これらのマーカー間にあるディレクティブへのいかなる変更も上書きされてしまいます。
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule .* - [E=REMOTE_USER:%{HTTP:Authorization}]
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>

# END WordPress

修正が終わったら、プロフィール画面をリロードします。

エラーが消えました。
パスワード名(パスワードではなく、管理キー)を入力し、「Add New」を押します。

パスワードが表示されるので、大事に保管しておきます。

パスワードを忘れてしまったら、「Revoke」で削除し再作成しましょう。

APIを試してみる

早速APIを試してみましょう。
今回はPostmanを使います。

GET: /posts

まずは投稿を取得してみます。

リファレンス

エンドポイントはこちら。

${basePath}/wp-json/wp/v2/posts

AuthorizationでBasic Authを選択し、
WordPressのユーザ名と先ほど作成したパスワードを入力します。

結果が返ってきました。
デフォルトだと投稿日の新しい順に、公開済みの投稿が10件取れるようです。

POST: /posts

次は投稿してみます。

リファレンス

エンドポイントは先ほどと同様です。

タイトル、本文、概要は必須項目のようです。
ヘッダに「Content-Type: application/json」を入れています。

APIを叩き返ってきたレスポンスがこちら。

{
    "id": 521,
    "date": "2020-05-30T16:22:32",
    "date_gmt": "2020-05-30T07:22:32",
    "guid": {
        "rendered": "https://autohacks.net/?p=521",
        "raw": "https://autohacks.net/?p=521"
    },
    "modified": "2020-05-30T16:22:32",
    "modified_gmt": "2020-05-30T07:22:32",
    "password": "",
    "slug": "",
    "status": "draft",
    "type": "post",
    "link": "https://autohacks.net/?p=521",
    "title": {
        "raw": "TEST",
        "rendered": "TEST"
    },
    "content": {
        "raw": "<h1>テスト</h1>\n\n<h1>テスト</h1>",
        "rendered": "<h1 id=\"outline__1\">テスト</h1>\n<h1 id=\"outline__1\">テスト</h1>\n",
        "protected": false,
        "block_version": 0
    },
    "excerpt": {
        "raw": "# テスト",
        "rendered": "<p># テスト</p>\n",
        "protected": false
    },
    "author": 1,
    "featured_media": 0,
    "comment_status": "open",
    "ping_status": "open",
    "sticky": false,
    "template": "",
    "format": "standard",
    "meta": {
        "spay_email": "",
        "jetpack_publicize_message": ""
    },
    "categories": [
        1
    ],
    "tags": [],
    "permalink_template": "https://autohacks.net/%postname%/",
    "generated_slug": "test",
    "jetpack_featured_media_url": "",
    "jetpack_publicize_connections": [],
    "jetpack_sharing_enabled": true,
    "jetpack_likes_enabled": false,
    "jetpack-related-posts": [],
    "_links": {
        "self": [
            {
                "href": "https://autohacks.net/wp-json/wp/v2/posts/521"
            }
        ],
        "collection": [
            {
                "href": "https://autohacks.net/wp-json/wp/v2/posts"
            }
        ],
        "about": [
            {
                "href": "https://autohacks.net/wp-json/wp/v2/types/post"
            }
        ],
        "author": [
            {
                "embeddable": true,
                "href": "https://autohacks.net/wp-json/wp/v2/users/1"
            }
        ],
        "replies": [
            {
                "embeddable": true,
                "href": "https://autohacks.net/wp-json/wp/v2/comments?post=521"
            }
        ],
        "version-history": [
            {
                "count": 0,
                "href": "https://autohacks.net/wp-json/wp/v2/posts/521/revisions"
            }
        ],
        "wp:attachment": [
            {
                "href": "https://autohacks.net/wp-json/wp/v2/media?parent=521"
            }
        ],
        "wp:term": [
            {
                "taxonomy": "category",
                "embeddable": true,
                "href": "https://autohacks.net/wp-json/wp/v2/categories?post=521"
            },
            {
                "taxonomy": "post_tag",
                "embeddable": true,
                "href": "https://autohacks.net/wp-json/wp/v2/tags?post=521"
            }
        ],
        "wp:action-publish": [
            {
                "href": "https://autohacks.net/wp-json/wp/v2/posts/521"
            }
        ],
        "wp:action-unfiltered-html": [
            {
                "href": "https://autohacks.net/wp-json/wp/v2/posts/521"
            }
        ],
        "wp:action-sticky": [
            {
                "href": "https://autohacks.net/wp-json/wp/v2/posts/521"
            }
        ],
        "wp:action-assign-author": [
            {
                "href": "https://autohacks.net/wp-json/wp/v2/posts/521"
            }
        ],
        "wp:action-create-categories": [
            {
                "href": "https://autohacks.net/wp-json/wp/v2/posts/521"
            }
        ],
        "wp:action-assign-categories": [
            {
                "href": "https://autohacks.net/wp-json/wp/v2/posts/521"
            }
        ],
        "wp:action-create-tags": [
            {
                "href": "https://autohacks.net/wp-json/wp/v2/posts/521"
            }
        ],
        "wp:action-assign-tags": [
            {
                "href": "https://autohacks.net/wp-json/wp/v2/posts/521"
            }
        ],
        "curies": [
            {
                "name": "wp",
                "href": "https://api.w.org/{rel}",
                "templated": true
            }
        ]
    }
}

いきなり公開されてしまうかと思いきや、デフォルトだと下書きで投稿されるようですね。

私は「WP Editor.md」プラグインを入れてマークダウンで記事を書いているのですが、
それのおかげか分かりませんが、マークダウンのまま投稿しても本文をHTMLに変換してくれるようです。

てっきりHTML変換が必要なものと思っていたので、これはかなり助かります。

管理画面からも、投稿を確認できました。

POST: /media

最後に画像を投稿してみます。

リファレンス

エンドポイントはこちら。

${basePath}/wp-json/wp/v2/media

まずはPostmanの作業ディレクトリ(画像の置き先)を確認しておきます。

スパナアイコンをクリック -> Settingsを開き、
Generalタブを下までスクロールします。

Locationのパスが、画像ファイルの置き先です。
変更したい場合は、「Choose」でディレクトリを選択します。

作業ディレクトリに画像をおいたら、リクエストボディに追加しましょう。

Bodyタブで「form-data」を選択し、KEYを「file」とします。

KEYテキストエリアの末尾〜VALUEテキストエリアにマウスカーソルを持っていくと、「Text」と表示されたプルダウンが出てきます。ここを「File」に変えて、「Select Files」をクリックし画像を選択します。

APIを叩き返ってきたレスポンスがこちら。

{
    "id": 524,
    "date": "2020-05-30T17:11:40",
    "date_gmt": "2020-05-30T08:11:40",
    "guid": {
        "rendered": "https://autohacks.net/wp-content/uploads/2020/05/FirstView.png",
        "raw": "https://autohacks.net/wp-content/uploads/2020/05/FirstView.png"
    },
    "modified": "2020-05-30T17:11:40",
    "modified_gmt": "2020-05-30T08:11:40",
    "slug": "firstview",
    "status": "inherit",
    "type": "attachment",
    "link": "https://autohacks.net/firstview/",
    "title": {
        "raw": "FirstView",
        "rendered": "FirstView"
    },
    "author": 1,
    "comment_status": "open",
    "ping_status": "closed",
    "template": "",
    "meta": {
        "spay_email": ""
    },
    "permalink_template": "https://autohacks.net/?attachment_id=524",
    "generated_slug": "firstview",
    "jetpack_sharing_enabled": true,
    "jetpack_likes_enabled": false,
    "description": {
        "raw": "",
        "rendered": "<p class=\"attachment\"><a href='https://autohacks.net/wp-content/uploads/2020/05/FirstView.png'><img width=\"300\" height=\"225\" src=\"https://autohacks.net/wp-content/uploads/2020/05/FirstView-300x225.png\" class=\"attachment-medium size-medium\" alt=\"\" srcset=\"https://autohacks.net/wp-content/uploads/2020/05/FirstView-300x225.png 300w, https://autohacks.net/wp-content/uploads/2020/05/FirstView-768x576.png 768w, https://autohacks.net/wp-content/uploads/2020/05/FirstView.png 800w\" sizes=\"(max-width: 300px) 100vw, 300px\" /></a></p>\n"
    },
    "caption": {
        "raw": "",
        "rendered": ""
    },
    "alt_text": "",
    "media_type": "image",
    "mime_type": "image/png",
    "media_details": {
        "width": 800,
        "height": 600,
        "file": "2020/05/FirstView.png",
        "sizes": {
            "medium": {
                "file": "FirstView-300x225.png",
                "width": 300,
                "height": 225,
                "mime_type": "image/png",
                "source_url": "https://autohacks.net/wp-content/uploads/2020/05/FirstView-300x225.png"
            },
            "thumbnail": {
                "file": "FirstView-150x150.png",
                "width": 150,
                "height": 150,
                "mime_type": "image/png",
                "source_url": "https://autohacks.net/wp-content/uploads/2020/05/FirstView-150x150.png"
            },
            "medium_large": {
                "file": "FirstView-768x576.png",
                "width": 768,
                "height": 576,
                "mime_type": "image/png",
                "source_url": "https://autohacks.net/wp-content/uploads/2020/05/FirstView-768x576.png"
            },
            "full": {
                "file": "FirstView.png",
                "width": 800,
                "height": 600,
                "mime_type": "image/png",
                "source_url": "https://autohacks.net/wp-content/uploads/2020/05/FirstView.png"
            }
        },
        "image_meta": {
            "aperture": "0",
            "credit": "",
            "camera": "",
            "caption": "",
            "created_timestamp": "0",
            "copyright": "",
            "focal_length": "0",
            "iso": "0",
            "shutter_speed": "0",
            "title": "",
            "orientation": "0",
            "keywords": []
        }
    },
    "post": null,
    "source_url": "https://autohacks.net/wp-content/uploads/2020/05/FirstView.png",
    "missing_image_sizes": [],
    "_links": {
        "self": [
            {
                "href": "https://autohacks.net/wp-json/wp/v2/media/524"
            }
        ],
        "collection": [
            {
                "href": "https://autohacks.net/wp-json/wp/v2/media"
            }
        ],
        "about": [
            {
                "href": "https://autohacks.net/wp-json/wp/v2/types/attachment"
            }
        ],
        "author": [
            {
                "embeddable": true,
                "href": "https://autohacks.net/wp-json/wp/v2/users/1"
            }
        ],
        "replies": [
            {
                "embeddable": true,
                "href": "https://autohacks.net/wp-json/wp/v2/comments?post=524"
            }
        ],
        "wp:action-unfiltered-html": [
            {
                "href": "https://autohacks.net/wp-json/wp/v2/media/524"
            }
        ],
        "wp:action-assign-author": [
            {
                "href": "https://autohacks.net/wp-json/wp/v2/media/524"
            }
        ],
        "curies": [
            {
                "name": "wp",
                "href": "https://api.w.org/{rel}",
                "templated": true
            }
        ]
    }
}

リサイズ版も自動で作ってくれていますね。

管理画面からも、画像の追加を確認できました。

ちなみに同じリクエストをもう一度叩いてみたところ、
ファイル名を自動で「FirstView-1.png」に変更して追加してくれました。

画像をPOSTしてレスポンスからファイル名を受け取るようにすれば、
誤って過去の画像を上書きしてしまうこともなく画像を記事に埋め込めそうですね。


今回はここまで。

使ってみて思ったのは、APIでも想像以上にWP側で色々やってくれるということです。
マークダウンのHTML変換とか画像のリサイズとか、
管理画面から操作するからこそやってくれるものと思っていましたが、
APIでもやってくれるということで、案外簡単に自動化できそうです。

引き続きこのWP REST APIを使って、
投稿を自動化していきたいと思います。