WordPressのREST APIを使ってPythonから自動投稿2

ブログ

前回の記事ではWordPressREST APIを使って、投稿を行う方法を紹介しました。

今回は、もう少し簡単に投稿を行えるようにするために、カテゴリー、タグ、投稿日の設定を行いたいと思います。

投稿時に設定できる変数

REST APIの投稿メソッドの変数は以下です。
– title: 投稿のタイトル(string)
– content: 投稿の内容(string)
– excerpt: 投稿の抜粋(string)
– status: 投稿のステータス(string; 例: publish, draft, pendingなど)
– author: 投稿の著者ID(integer)
– comment_status: コメントの状態(string; 例: open, closed)
– ping_status: ピンバックの状態(string; 例: open, closed)
– format: 投稿のフォーマット(string; 例: standard, aside, galleryなど)
– slug: 投稿のスラッグ(string)
– date: 投稿の公開日時(string; ISO8601形式, datetime型は自動変換)
– date_gmt: 投稿の公開日時(GMT; string; ISO8601形式, datetime型は自動変換)
– modified: 投稿の最終更新日時(string; ISO8601形式)
– modified_gmt: 投稿の最終更新日時(GMT; string; ISO8601形式)
– categories: 投稿に関連付けられたカテゴリIDの配列(array of integer)
– tags: 投稿に関連付けられたタグIDの配列(array of integer)
– featured_media: アイキャッチ画像のメディアID(integer)

この中で、カテゴリーとタグは、通常文字列で指定したいと思いますが、実際はIDを指定する必要があります。
そのため、REST APIを使って、カテゴリーやタグの一覧を取得して、自動でIDをセットするようにしたいと思います。

また、日付関連は、datetimeで指定された場合にISO8601形式に変換するようにします。

カテゴリー取得のメソッド

まずは、カテゴリー一覧を取得するメソッドを作成します。
前回の投稿作成時に作ったWordPressClientクラスに追加するメソッドです。

    def update_category_cache(self):
        """ カテゴリーのキャッシュを更新する """
        categories = self.get_categories()
        self.category_cache = {category['name']: category['id'] for category in categories}


    def get_categories(self):
        """
        すべてのカテゴリーを取得する
        :return: カテゴリーのリスト
        """
        endpoint = "categories"
        categories = []
        page = 1
        per_page = 100  # 一度に取得するアイテムの数(必要に応じて調整)

        while True:
            response = self.request("GET", endpoint, data={'per_page': per_page, 'page': page})
            if not response:
                break

            categories.extend(response)

            if len(response) < per_page:
                break

            page += 1

        return categories

続いて、カテゴリー名を指定したときにカテゴリーのIDを返すメソッドを作成します。

すでにカテゴリーが存在する場合は、IDを返すのみ、存在しない場合は、新しくカテゴリーを作成します。

def create_category(self, name, **kwargs):
        """
        新しいカテゴリーを作成する
        :param name: カテゴリーの名前
        :param kwargs: カテゴリーのその他のデータ(スラッグなど)
        :return: カテゴリーのID
        """
        endpoint = "categories"
        category_data = {
            'name': name,
            **kwargs
        }
        response = self.request("POST", endpoint, data=category_data)
        category_id = response.get('id')
        self.category_cache[name] = category_id
        return category_id

    def get_or_create_category_id(self, name, **kwargs):
        """
        カテゴリー名を指定して、そのIDを取得する。存在しない場合は新規作成する
        :param name: カテゴリーの名前
        :param kwargs: カテゴリーのその他のデータ(スラッグなど)
        :return: カテゴリーのID
        """
        # キャッシュをチェック
        if name in self.category_cache:
            return self.category_cache[name]

        # カテゴリーが存在しない場合、新規作成
        return self.create_category(name, **kwargs)

タグの取得

同様にタグについても処理を行います。


    def update_tag_cache(self):
        """ タグのキャッシュを更新する """
        tags = self.get_tags()
        self.tag_cache = {tag['name']: tag['id'] for tag in tags}

    def get_tags(self):
        """
        すべてのタグを取得する
        :return: タグのリスト
        """
        endpoint = "tags"
        tags = []
        page = 1
        per_page = 100  # 一度に取得するアイテムの数(必要に応じて調整)

        while True:
            response = self.request("GET", endpoint, data={'per_page': per_page, 'page': page})
            if not response:
                break

            tags.extend(response)

            if len(response) < per_page:
                break

            page += 1

        return tags

    def create_tag(self, name, **kwargs):
        """
        新しいタグを作成する
        :param name: タグの名前
        :param kwargs: タグのその他のデータ(スラッグなど)
        :return: タグのID
        """
        endpoint = "tags"
        tag_data = {
            'name': name,
            **kwargs
        }
        response = self.request("POST", endpoint, data=tag_data)
        tag_id = response.get('id')
        self.tag_cache[name] = tag_id
        return tag_id

    def get_or_create_tag_id(self, name, **kwargs):
        """
        タグ名を指定して、そのIDを取得する。存在しない場合は新規作成する
        :param name: タグの名前
        :param kwargs: タグのその他のデータ(スラッグなど)
        :return: タグのID
        """
        # キャッシュをチェック
        if name in self.tag_cache:
            return self.tag_cache[name]

        # タグが存在しない場合、新規作成
        return self.create_tag(name, **kwargs)

カテゴリー、タグの取得と作成

これらのメソッドは以下のように使います

# カテゴリーの取得または作成
category_name = "カテゴリー1"
category_id = wp_client.get_or_create_category_id(category_name)
print(f"Category '{category_name}' ID: {category_id}")

# タグの取得または作成
tag_name = "タグ1"
tag_id = wp_client.get_or_create_tag_id(tag_name)
print(f"Tag '{tag_name}' ID: {tag_id}")

# もう一度同じカテゴリーを取得してIDを確認
category_id_again = wp_client.get_or_create_category_id(category_name)
print(f"Category '{category_name}' ID (again): {category_id_again}")

# もう一度同じタグを取得してIDを確認
tag_id_again = wp_client.get_or_create_tag_id(tag_name)
print(f"Tag '{tag_name}' ID (again): {tag_id_again}")

投稿メソッドの修正

カテゴリーとタグの取得機能を作成できたので、投稿部分のメソッドに修正を加えます。

def create_or_update(self, post_type, item_id=None, **kwargs):
        """
        WordPressに投稿またはページを作成または更新する
        :param post_type: 'posts' または 'pages' など、作成または更新するアイテムの種類
        :param item_id: 更新するアイテムのID(新規作成の場合はNone)
        :param kwargs: アイテムのデータ(タイトル、コンテンツ、ステータス、親ページIDなど)
        :return: アイテムID
        """
        # アイテムデータ
        item_data = {key: value for key, value in kwargs.items() if value is not None}

        # date および date_gmt の変換
        if 'date' in kwargs and isinstance(kwargs['date'], datetime):
            item_data['date'] = self.format_date_for_wp(kwargs['date'])
        if 'date_gmt' in kwargs and isinstance(kwargs['date_gmt'], datetime):
            item_data['date_gmt'] = self.format_date_for_wp(kwargs['date_gmt'])

        # カテゴリーとタグをIDに変換
        if 'categories' in kwargs:
            item_data['categories'] = [self.get_or_create_category_id(cat_name.strip()) for cat_name in kwargs['categories'] if cat_name.strip() != '']

        if 'tags' in kwargs:
            item_data['tags'] = [self.get_or_create_tag_id(cat_name.strip()) for cat_name in kwargs['tags'] if cat_name.strip() != '']

        if item_id:
            # アイテムの更新
            endpoint = f"{post_type}/{item_id}"
            method = "PUT"  # 更新にはPUTメソッドを使用
        else:
            # 新規アイテムの作成
            endpoint = post_type
            method = "POST"

        # アイテムを作成または更新するリクエスト
        response = self.request(method, endpoint, data=item_data)
        return response.get('id')


    def create_post(self, post_id=None, **kwargs):
        """
        WordPressに投稿を作成または更新する
        :param post_id: 更新する投稿のID(新規作成の場合はNone)
        :param kwargs: 投稿のデータ(タイトル、コンテンツ、ステータス、カテゴリーなど)
        :return: 投稿ID
            title: 投稿のタイトル(string)
            content: 投稿の内容(string)
            excerpt: 投稿の抜粋(string)
            status: 投稿のステータス(string; 例: publish, draft, pendingなど)
            author: 投稿の著者ID(integer)
            comment_status: コメントの状態(string; 例: open, closed)
            ping_status: ピンバックの状態(string; 例: open, closed)
            format: 投稿のフォーマット(string; 例: standard, aside, galleryなど)
            slug: 投稿のスラッグ(string)
            date: 投稿の公開日時(string; ISO8601形式, datetime型は自動変換)
            date_gmt: 投稿の公開日時(GMT; string; ISO8601形式, datetime型は自動変換)
            modified: 投稿の最終更新日時(string; ISO8601形式)
            modified_gmt: 投稿の最終更新日時(GMT; string; ISO8601形式)
            categories: 投稿に関連付けられたカテゴリIDの配列(array of integer)
            tags: 投稿に関連付けられたタグIDの配列(array of integer)
            featured_media: アイキャッチ画像のメディアID(integer)
        """
        return self.create_or_update("posts", post_id, **kwargs)

    @staticmethod
    def format_date_for_wp(dt):
        """ISO 8601形式の文字列に変換する関数"""
        return dt.isoformat()

format_date_for_wpを使って、日付の形式を変換できるようにします。

固定ページの作成

固定ページについても投稿とほぼ同じように行えるため、ページ作成用のメソッドも作成します。

    def create_page(self, page_id=None, **kwargs):
        """
        WordPressにページを作成または更新する
        :param page_id: 更新するページのID(新規作成の場合はNone)
        :param kwargs: ページのデータ(タイトル、コンテンツ、ステータス、親ページIDなど)
        :return: ページID
        """
        return self.create_or_update("pages", page_id, **kwargs)

クラスの初期化

クラスの初期化部分にタグやカテゴリーの一覧を取得する部分を追加します。

    def __init__(self, wp_url, auth_method, auth_info):
        """
        WordPress APIクライアントの初期化
        :param wp_url: WordPressサイトのURL
        :param auth_method: 認証方法 ("application_password", "jwt", "oauth1")
        :param auth_info: 認証情報の辞書
        """
        self.wp_url = wp_url
        self.auth_method = auth_method
        self.auth_info = auth_info
        self.headers = {}

        self.category_cache = {}
        self.tag_cache = {}

        # 認証設定
        self.set_auth()

        self.update_category_cache()
        self.update_tag_cache()

投稿例

例えば、次のようにして投稿を作成できます。
予約投稿の例を作成費ます。

#予約投稿
import pytz
from datetime import datetime, timedelta
import os
# タイムゾーンを日本に設定
japan_tz = pytz.timezone('Asia/Tokyo')
# 現在の日時を日本標準時で取得
date = datetime.now(japan_tz) + timedelta(days=1)
# 新しい投稿を作成
new_post_id = wp_client.create_post(
    title="New Post Title",
    content="This is the content of the new post.",
    status="future",
    categories=['カテゴリー1'],
    tags=['タグ1','タグ2'],
    date_gmt = date,
)
print(f"New post created with ID: {new_post_id}")

まとめ

これで投稿時にカテゴリーやタグ、日付などを簡単に設定できるようになりました。

次回は、画像のアップロード関連のやり方を解説します。

コメント

タイトルとURLをコピーしました