Warning: Undefined variable $position in /home/pystyles/pystyle.info/public_html/wp/wp-content/themes/lionblog/functions.php on line 4897

Python から XML-RPC を介して WordPress を操作する方法

Python から XML-RPC を介して WordPress を操作する方法

概要

Python から WordPress ブログにコンテンツを投稿したり、画像をアップロードするといった各種操作を行う方法について解説します。 これらの操作は WordPress が提供している XML-RPC API を介して行います。

XML-RPC による通信は、標準ライブラリの xmlrpc.client でもできますが、今回は WordPress への XML-RPC による通信をライブラリ化した python-wordpress-xmlrpc を使って行います。

Advertisement

XML-RPC と WordPress API

XML-RPC は HTTP 経由で、XML を使って遠隔手続き呼び出しを実現する方法です。 WordPress は、コンテンツの投稿や更新といった各種操作を他のアプリケーションから行えるように、XML-RPC を介した API を提供しています。 API の仕様は XML-RPC WordPress API で確認できます。

インストール

pip でインストールできます。

pip install python-wordpress-xmlrpc

クライアントの作成

まず、通信を行うクライアントを作成します。

Client(url, username, password)
  • 引数
    • url: xmlrpc.php の URL を指定します。
      ブログのログイン画面が https://sample.info/wp/wp-admin/ だとすると、xmlrpc.phphttps://sample.info/wp/xmlrpc.php にあります。
    • username: ログイン時のユーザー名
    • password: ログイン時のパスワード
In [1]:
from getpass import getpass

from wordpress_xmlrpc import Client, WordPressPost, methods

url = "https://pystyle.info/wp/xmlrpc.php"
user = getpass("ユーザー名")
password = getpass("パスワード")

client = Client(url, user, password)

コンテンツの操作

python-wordpress-xmlrpc は、投稿など実行したい操作を表す Methods オブジェクトを作成し、それを Client.call() に渡して呼び出す Command パターン のインタフェースになっています。

タイトル 概要
methods.posts.GetPosts コンテンツ一覧を取得する。
methods.posts.GetPost 特定のコンテンツを取得する。
methods.posts.NewPost コンテンツを投稿する。
methods.posts.EditPost 既存のコンテンツを編集する。
methods.posts.DeletePost コンテンツ、添付ファイルを削除する。
methods.posts.GetPostStatusList コンテンツの状態 post_status がとり得る値の一覧を返します。
methods.posts.GetPostFormats コンテンツの形式 post_format がとり得る値の一覧を返します。
methods.posts.GetPostTypes コンテンツの種類 post_type がとり得る値の一覧を返します。
Advertisement

コンテンツ一覧を取得する。

methods.posts.GetPosts を使うと、ブログ上のコンテンツ一覧を取得できます。

methods.posts.GetPosts([filter, fields])
  • 引数
    • filter: フィルタ条件
    • fields: 取得する項目

filter には取得する際の条件を dict で指定します。

{
    "number": 取得する最大数,
    "offset": オフセット,
    "orderby": ソートに使用する項目,
    "order": ソート順序 ("ASC": 昇順, "DESC": 降順),
    "post_type": コンテンツの種類 ("post": 記事, "page": 固定ページ)
    "post_status": コンテンツの状態 ("publish": 公開中, "draft": 下書き),
}

コンテンツを n 個ずつ取得する

コンテンツを n 個ずつ取得したい場合は、フィルタ条件で numberoffset を使用します。

In [2]:
# 20件ずつ取得したい場合、
number = 20  # 一度に取得するコンテンツ数
offset = 0  # オフセット
while True:
    posts = client.call(methods.posts.GetPosts({"number": number, "offset": offset}))
    if len(posts) == 0:
        break  # これ以上取得するコンテンツがない場合

    for post in posts:
        print(post.id, post.title)

    offset += number
1750 matplotlib - カラーマップを自作する方法について
1332 OpenCV - 画像をグリッド上に分割する、複数の画像をグリッド上に結合する方法
850 OpenCV - 画像処理の2値化の仕組みと cv2.threshold() の使い方
693 物体検出で使われる評価指標 mAP について解説
671 Python - 顔認識ライブラリ Face Recognition で顔検出を行う方法
665 matplotlib - コピペするだけで matplotlib を日本語化する方法 (Windows / Ubuntu 対応)
643 Python - 顔認識ライブラリ Face Recognition で顔認証を行う方法
600 Python から XML-RPC を介して WordPress を操作する方法
544 Pytorch - Fashion-MNIST で CNN モデルによる画像分類を行う
55 2020年版 Deep Learning ライブラリの選び方

記事を取得する順番を変更する

デフォルトでは、投稿日時が最新のコンテンツから取得するようになっていますが、orderby でソートする項目を変更できます。 また、order でソートを降順でするか、昇順でするかを変更できます。

In [3]:
# 更新日時が古い順に取得する。
posts = client.call(
    methods.posts.GetPosts({"orderby": "post_modified", "order": "ASC"})
)
for post in posts:
    print(post.id, post.title)
1332 OpenCV - 画像をグリッド上に分割する、複数の画像をグリッド上に結合する方法
544 Pytorch - Fashion-MNIST で CNN モデルによる画像分類を行う
643 Python - 顔認識ライブラリ Face Recognition で顔認証を行う方法
600 Python から XML-RPC を介して WordPress を操作する方法
671 Python - 顔認識ライブラリ Face Recognition で顔検出を行う方法
693 物体検出で使われる評価指標 mAP について解説
850 OpenCV - 画像処理の2値化の仕組みと cv2.threshold() の使い方
665 matplotlib - コピペするだけで matplotlib を日本語化する方法 (Windows / Ubuntu 対応)
55 2020年版 Deep Learning ライブラリの選び方
1750 matplotlib - カラーマップを自作する方法について

特定のコンテンツを取得する

methods.posts.GetPost を使うと、指定した ID のコンテンツを直接取得できます。 返り値は、コンテンツの情報を表す WordPressPost オブジェクトです。

methods.posts.GetPost(post_id[, fields])
  • 引数
    • post_id: コンテンツ ID
    • fields: 取得する項目

WordPressPost オブジェクトの属性、XML-RPC WordPress API の項目の対応表

XML-RPC 上の項目 WordPressPost の属性 意味
post_id id ID
post_title title タイトル
post_date date 作成日時
post_date_gmt 作成日時 (GMT)
post_modified date_modified 更新日時
post_modified_gmt 作成日時 (GMT)
post_status post_status 状態 (“publish”: 公開中, “draft”: 下書き)
post_type post_type 種類 (“post”: 記事, “page”: 固定ページ)
post_format post_format 形式
post_name slug スラグ
post_author user 投稿したユーザー ID
post_password password 閲覧パスワード
post_excerpt excerpt 概要
post_content content 内容
post_parent parent_id 親コンテンツの ID
post_mime_type mime_type minetype
link link URL
guid guid URL (ID)
menu_order menu_order メニューオーダー
comment_status comment_status コメントを受け付けるかどうか (“open”: 受付, “close”: 閉鎖)
ping_status ping_status ピンを受け付けるかどうか (“open”: 受付, “close”: 閉鎖)
sticky sticky ブログトップに固定するかどうか
post_thumbnail thumbnail アイキャッチ画像
terms terms カテゴリ及びタグ
terms_names
custom_fields
enclosure
In [4]:
import pandas as pd

fields = [
    ["ID", "id"],
    ["タイトル", "title"],
    ["作成日時", "date"],
    ["更新日時", "date_modified"],
    ["状態", "post_status"],
    ["種類", "post_type"],
    ["形式", "post_format"],
    ["スラグ", "slug"],
    ["投稿したユーザー ID", "user"],
    ["閲覧パスワード", "password"],
    ["概要", "excerpt"],
    # ["内容", "content"],
    ["親コンテンツの ID", "parent_id"],
    ["minetype", "mime_type"],
    ["URL", "link"],
    ["URL (ID)", "guid"],
    ["メニューオーダー", "menu_order"],
    ["コメントを受け付けるかどうか", "comment_status"],
    ["ピンを受け付けるかどうか", "ping_status"],
    ["ブログトップに固定するかどうか", "sticky"],
    # ["アイキャッチ画像", "thumbnail"],
    # ["カテゴリ及びタグ", "terms"],
]

post = client.call(methods.posts.GetPost(544))

df = []
for name, attr in fields:
    df.append({"属性名": attr, "内容": name, "値": getattr(post, attr)})
pd.DataFrame(df)
属性名 内容
0 id ID 544
1 title タイトル Pytorch – Fashion-MNIST で CNN モデルによる画像分類を行う
2 date 作成日時 2020-02-16 16:34:56
3 date_modified 更新日時 2020-03-15 14:54:25
4 post_status 状態 publish
5 post_type 種類 post
6 post_format 形式 standard
7 slug スラグ pytorch-cnn-based-classification-model-with-fa…
8 user 投稿したユーザー ID 1
9 password 閲覧パスワード
10 excerpt 概要
11 parent_id 親コンテンツの ID 0
12 mime_type minetype
13 link URL https://pystyle.info/pytorch-cnn-based-classif…
14 guid URL (ID) https://pystyle.info/?p=544
15 menu_order メニューオーダー 0
16 comment_status コメントを受け付けるかどうか open
17 ping_status ピンを受け付けるかどうか open
18 sticky ブログトップに固定するかどうか False

コンテンツを投稿する

まず、WordPressPost オブジェクトを作成し、コンテンツのタイトルや内容を各属性に設定します。 設定できたら、methods.posts.NewPost を使い、コンテンツを投稿できます。 投稿に成功すると、コンテンツ ID が返ります。

methods.posts.NewPost(content)
  • 引数
    • content: コンテンツ
  • 返り値
    • コンテンツ ID
In [5]:
# コンテンツを作成する。
post = WordPressPost()
post.title = "新しい記事"
post.content = "記事の内容"
post.terms_names = {"post_tag": ["Python", "WordPress"], "category": ["Python"]}

# コンテンツを投稿する。
post_id = client.call(methods.posts.NewPost(post))
print(post_id)
1824

既存のコンテンツを編集する。

methods.posts.EditPost を使用すると、指定した ID のコンテンツを上書きできます。

まず、methods.posts.GetPost で編集したいコンテンツを取得し、返り値の WordPressPost オブジェクトの編集したい属性を変更します。 変更したら、methods.posts.EditPost を使い、コンテンツを上書きできます。

methods.posts.EditPost(post_id, content)
  • 引数
    • post_id: 上書きするコンテンツの ID
    • content: コンテンツ
  • 返り値
    • 上書きに成功した場合は True を返します。
In [6]:
# 編集するコンテンツを取得する。
post = client.call(methods.posts.GetPost(post_id))
post.title = "編集したタイトル"
post.content = "編集した内容"

# コンテンツを更新する。
ret = client.call(methods.posts.EditPost(post_id, post))
print(ret)
True
Advertisement

既存のコンテンツを削除する。

methods.posts.DeletePost を使用すると、指定した ID のコンテンツを削除できます。

methods.posts.DeletePost(post_id)
  • 引数
    • post_id: 削除するコンテンツの ID
  • 返り値
    • 削除に成功した場合は True を返します。
In [7]:
ret = client.call(methods.posts.DeletePost(post_id))
print(ret)
True

添付ファイルの操作

タイトル 概要
methods.media.UploadFile 添付ファイルをアップデートする。
methods.media.GetMediaLibrary 添付ファイル一覧を取得する。
methods.media.GetMediaItem 特定の添付ファイルを取得する。

添付ファイルをアップロードする。

methods.media.UploadFile を使用すると、ブログで使用したい画像などをアップロードできます。

まず以下の辞書を作成します。

data = {
    "post_id": 添付ファイルを紐付けるコンテンツ ID (任意)
    "name": ファイル名,
    "type": minetype,
    "bits": データを表すバイト列から作成した xmlrpc_client.Binary オブジェクト
}

post_id は任意なので、なくても構いません。

作成したら、methods.media.UploadFile を使い、データをアップデートできます。

methods.media.UploadFile(data)
  • 引数
    • data: アップデートするデータ
  • 返り値
    • アップロードに成功した場合は、ID や URL といった情報が格納された辞書が返ります。
In [8]:
import mimetypes
from pathlib import Path
from pprint import pprint

from wordpress_xmlrpc.compat import xmlrpc_client

# ファイルを読み込む。
filepath = Path("sample.png")
with open(filepath, "rb") as f:
    binary = xmlrpc_client.Binary(f.read())

# ファイルの minetype を取得する。
minetype = mimetypes.guess_type(filepath)[0]
print(minetype)

data = {
    "post_id": post_id,  # 添付ファイルを紐付けるコンテンツ ID
    "name": filepath.name,  # WordPress 上のファイル名
    "type": "image/jpeg",  # mimetype
    "bits": binary,  # データ
}

# アップロードする。
res = client.call(methods.media.UploadFile(data))
print(f"添付ファイルの ID: {res['id']}")
print(f"WordPress 上のファイル名: {res['file']}")
print(f"WordPress 上の URL: {res['link']}")
print(f"添付ファイルが紐付いているコンテンツの ID: {res['parent']}")

attachment_id = res['id']
image/png
添付ファイルの ID: 1827
WordPress 上のファイル名: sample.png
WordPress 上の URL: https://pystyle.info/wp/wp-content/uploads/2020/03/sample.png
添付ファイルが紐付いているコンテンツの ID: 1824

添付ファイル一覧を取得する

methods.media.GetMediaLibrary を使うと、添付ファイル一覧を取得できます。

methods.media.GetMediaLibrary(filter)
  • 引数
    • filter: フィルタ条件

filter には取得する際の条件を dict で指定します。

{
    "number": 取得する最大数,
    "offset": オフセット,
    "parent_id": 添付ファイルが紐付いているコンテンツの ID,
    "mime_type": minetype,
}
In [9]:
# ID post_id に紐づく添付ファイル一覧を取得する。
files = client.call(methods.media.GetMediaLibrary({"parent_id": post_id}))
for file in files:
    print(file.id, file.title)
1827 sample.png
Advertisement

特定の添付ファイルを取得する。

methods.media.GetMediaItem を使うと、指定した ID の添付ファイルを取得できます。 返り値は、添付ファイルの情報を表す WordPressMedia オブジェクトです。

methods.media.GetMediaItem(attachmend_id)
  • 引数
    • attachmend_id: 添付ファイル ID

WordPressMedia オブジェクトの属性、XML-RPC WordPress API の項目名の対応表

XML-RPC 上の項目名 WordPressMedia の属性 意味
attachment_id id ID
date_created_gmt date_created 作成日時 (GMT)
parent parent 紐付いているコンテンツの ID
link link WordPress 上のURL
title title WordPress 上のファイル名
caption caption 注釈
description description 説明
metadata metadata メタデータ
thumbnail thumbnail サムネイルの URL
In [10]:
import pandas as pd

fields = [
    ["ID", "id"],
    ["作成日時 (GMT)", "date_created"],
    ["紐付いているコンテンツの ID", "parent"],
    ["WordPress 上のURL", "link"],
    ["WordPress 上のファイル名", "title"],
    ["注釈", "caption"],
    ["説明", "description"],
    ["メタデータ", "metadata"],
    ["サムネイルの URL", "thumbnail"],
]

# ID post_id のコンテンツの添付ファイル一覧を取得する。
files = client.call(methods.media.GetMediaItem(attachment_id))

df = []
for name, attr in fields:
    df.append({"属性名": attr, "内容": name, "値": getattr(files, attr)})
pd.DataFrame(df)
属性名 内容
0 id ID 1827
1 date_created 作成日時 (GMT) 2020-03-16 13:09:21
2 parent 紐付いているコンテンツの ID 1824
3 link WordPress 上のURL https://pystyle.info/wp/wp-content/uploads/202…
4 title WordPress 上のファイル名 sample.png
5 caption 注釈
6 description 説明
7 metadata メタデータ {‘width’: 512, ‘height’: 512, ‘file’: ‘2020/03…
8 thumbnail サムネイルの URL https://pystyle.info/wp/wp-content/uploads/202…

既存の添付ファイルを削除する。

methods.posts.DeletePost は、コンテンツを削除する他、添付ファイルの削除も行えます。 post_id に添付ファイルの ID を指定すると、削除できます。

In [11]:
ret = client.call(methods.posts.DeletePost(attachment_id))
print(ret)
True