Python

Python ChatGPTを活用してブログを完全自動化:【記事自動作成、自動投稿】③

この記事は、ChatGPTのAPIをPythonから利用し、「ブログ記事を自動で生成させ、更にWordpressへ自動投稿してしまおう!」という、ブログの運営者にとって夢の様なチュートリアルの最終回です!!

1回目の記事で、ChatGPTはPythonを介してAPIを利用できるようにして、前回の記事では実際にブログ記事の構成のHTMLへ組み立てる処理までを実装しました。

今回の記事では、実際にWordpressへ記事を投稿する処理の実装、自動化設定の方法などを詳しく書いていきたいと思います。

WordPressのREST API

WordPress REST APIとは、WP-CLIやURLベースでWordPress外部からウェブサイトのデータを取得できる仕組みのことです。

WordPress REST APIを利用することで、管理画面を通さずにWordPressの投稿や編集、更新、削除が可能です。

このREST APIという仕組みを使用して投稿する方法を解説します。

REST APIを有効化するには

REST APIを有効化するには、WordPressの管理画面にログインし、「設定」→「パーマリンク」からパーマリンクの設定を保存するだけで有効になります。パーマリンクの設定を保存することで確認できます。

REST APIで出来る事

REST APIでは下記に挙げるエンドポイントへアクセスすることで、データを取得したり更新や削除を行う事が出来ます。主要な物だけを紹介します。

投稿関連のエンドポイント

  1. /wp/v2/posts: 投稿の作成、取得、更新、削除などの操作を行います。
  2. /wp/v2/categories: カテゴリの作成、取得、更新、削除などの操作を行います。
  3. /wp/v2/tags: タグの作成、取得、更新、削除などの操作を行います。
  4. /wp/v2/media: メディア(画像や動画)のアップロード、取得、更新、削除などの操作を行います。

ユーザー関連のエンドポイント

  1. /wp/v2/users: ユーザーの作成、取得、更新、削除などの操作を行います。
  2. /wp/v2/users/me: 現在のユーザーの情報を取得します。

カスタム投稿タイプ関連のエンドポイント

  1. /wp/v2/{post_type}: カスタム投稿タイプに関する操作を行います。

コメント関連のエンドポイント

  1. /wp/v2/comments: コメントの作成、取得、更新、削除などの操作を行います。

カスタムエンドポイント

  1. サイトに独自のエンドポイントを追加して、カスタムな操作やデータの取得を行うことも可能です。

れらのエンドポイントを使用することで、WordPressサイトの投稿やカテゴリ、タグ、メディアなどの管理、ユーザー情報の取得、コメントの操作などが行えます。

各エンドポイントはHTTPメソッド(GET、POST、PUT、DELETEなど)を使用してアクセスし、JSON形式のデータを送受信します。必要なパラメータやヘッダーを指定してリクエストを行うことで各種操作が可能です。

REST APIのHTTPメソッドの使い分け

WordPress REST APIでは、次のHTTPメソッドを使ってデータやリソースのやりとりをします。

  1. GET(投稿などのデータを返してくれる)
  2. POST(新しいデータをサイトに追加できる)
  3. PUT(データを更新し、更新されたデータを返してくれる)
  4. DELETE(データを削除し、削除したデータを返してくれる)

今回は記事を投稿したいので、POSTを使用することになります。前の節で説明した通り、下記のURLへパラメータを設定してPOSTする事で記事の投稿が可能になります。

https://your-site-domain.com/wp-json/wp/v2/posts

PythonでWordPressのREST APIを使用

PythonからHTTPメソッドのPOSTを利用するには、requestsモジュールを使用する方法が簡単です。

まず、requestsモジュールをインストールします。下記のコマンドをターミナル若しくはコマンドプロンプトから実行しインストールしてください。

pip install requests

インストールが完了したら、テストを行う為に一度Pythonプロンプトを立ち上げて下記のコマンドを1行ずつ実行して見てください。

import requests # インストールに失敗していた場合、ここでエラーが発生します。

# WordPressのREST APIのエンドポイント
endpoint = 'https://your-site.com/wp-json/wp/v2/posts' # your-site.com は貴方のドメインに変更してください。

# GETリクエストで記事を取得
response = requests.get(endpoint)

# レスポンスのJSONデータを取得
posts = response.json()

# 取得した記事を表示
for post in posts:
    print(post['title']['rendered'])

私の環境で実装した所、下記のようになりました。

$ python # Pythonプロンプトの立ち上げ

>>> import requests
>>> endpoint = 'https://www.yuus-program.com/wp-json/wp/v2/posts'
>>> response = requests.get(endpoint)
>>> posts = response.json()
>>> for post in posts:
...     print(post['title']['rendered'])
...
# --- 下記が取得した内容です。 ---
Python ChatGPTを活用してブログを完全自動化:【記事自動作成、自動投稿】②
PHP入門ガイド: オブジェクト指向【徹底解説】
Python ChatGPTを活用してブログを完全自動化:【記事自動作成、自動投稿】①
【SQL】日付時間操作を完全マスター『どこよりも詳しく解説!』
PHP入門ガイド: データベース操作【徹底解説】
速習Linux – コマンド操作を極める【シェル芸の世界】
SQL入門ガイド: SELECT文を完全マスター【詳細解説】
SQL入門ガイド: MySQLのINSERT、UPDATE、DELETEの基本から応用まで完全解説
PHP入門ガイド: リクエスト情報の詳細と使い方【徹底解説】
PHP入門ガイド: 関数完全マスター【ユーザー定義関数の基礎から最新機能まで完全網羅】
>>>

最新の記事から10件、取得できている事がわかります。とても簡単なコードでデータが取得できます。

取得する件数は「_per_page」で指定することができます。「_per_page」は、1から100までの指定ができます。
例えば15件取得したい場合は下記の様に指定する事で取得可能です。

https://your-site.com/wp-json/wp/v2/posts?per_page=15

記事を投稿するPythonコード

記事を投稿するにはユーザー認証を行う必要があります。まず、WordPressの管理画面より、アプリケーションパスワードを設定してください。「設定」→「ユーザー」→「対象ユーザー選択」→「画面下部に下記の様な箇所があるので、任意の名前をつけて追加」

アプリケーションパスワードは再表示されませんので、ご注意ください。
また、パスワードの変更はできないので、「取消」で一旦削除してから再度作成する必要があります。

記事の投稿用のURLは先程説明した通りです。Pythonのrequestsモジュールを使用し、POSTリクエストを行うことで、投稿可能です。

import requests
from requests.auth import HTTPBasicAuth

# WordPressのREST APIのエンドポイント
endpoint = 'https://your-site.com/wp-json/wp/v2/posts'

# 認証情報
username = 'Wordpressのユーザー名'
password = '先程設定取得した、アプリケーションパスワード'

# 下書きとして投稿するデータ
data = {
    'title': '下書きのタイトル',
    'content': '下書きの内容',
    'status': 'draft'  # draft=下書き、publish=公開 省略時はdraftになる
}

# POSTリクエストで下書き投稿
response = requests.post(endpoint, json=data, auth=(username, password))

# レスポンスのJSONデータを取得
post = response.json()

# 投稿のIDを表示
print('下書きが作成されました。ID:', post['id'])

たったこれだけのコードで投稿が可能になります。基本認証(Basic Authentication)を使用していますので、必ず事前にアプリケーションパスワードを用意する必要があります。

トークンベースの認証(Token-based Authentication)を行う事も可能で。トークン認証はプラグインなどを使用し、トークンを生成する必要があります。

上記のコードを実行してWordpressの管理画面から投稿一覧を確認すると投稿の下書きが作成されている事がわかります。

カテゴリ、タグ、アイキャッチ画像設定

補足事項として、投稿時にカテゴリ、タグ、アイキャッチ画像を設定する方法を解説します。

カテゴリ設定

# 投稿データ
data = {
    'title': '投稿のタイトル',
    'content': '投稿の内容',
    'status': 'publish',
    'categories': [category_id]  # カテゴリIDを配列で指定
}

投稿データの辞書に「categories」を配列で追加するだけです。カテゴリIDは下記で調べられます。

import requests

# WordPressのREST APIのエンドポイント
endpoint = 'https://your-site.com/wp-json/wp/v2/categories'

# GETリクエストでカテゴリを取得
response = requests.get(endpoint)

# レスポンスのJSONデータを取得
categories = response.json()

# 取得したカテゴリの情報を表示
for category in categories:
    print(category['id'], category['name'])

指定したカテゴリと一致するものをresponseから取り出せば良いです。勿論、事前に管理画面から調べておいても構いません。

タグ設定

# 投稿データ
data = {
    'title': '投稿のタイトル',
    'content': '投稿の内容',
    'status': 'publish',
    'tags': [tag_id]  # タグIDを配列で指定
}

投稿データの辞書に「tags」を配列で追加するだけです。タグIDは下記で調べられます。

import requests

# WordPressのREST APIのエンドポイント
endpoint = 'https://your-site.com/wp-json/wp/v2/tags'

# GETリクエストでタグを取得
response = requests.get(endpoint)

# レスポンスのJSONデータを取得
tags = response.json()

# 取得したタグの情報を表示
for tag in tags:
    print(tag['id'], tag['name'])

指定したタグと一致するものをresponseから取り出せば良いです。勿論、事前に管理画面から調べておいても構いません。

アイキャッチ画像

アイキャッチ画像は、アップロードして設定するパターンと既にアップロード済みの画像を使用するパターンがあるので、以下でサンプルを示します。

アップロード済みのメディアを使用する場合

# 投稿データ
data = {
    'title': '投稿のタイトル',
    'content': '投稿の内容',
    'status': 'publish',
    'featured_media': media_id  # アイキャッチ画像のメディアIDを指定
}

featured_mediaへ、メディアIDを指定します。

アイキャッチ画像のアップロード

import requests

# WordPressのREST APIのエンドポイント(メディア)
media_endpoint = 'https://your-site.com/wp-json/wp/v2/media'

# アップロードする画像ファイルのパス
image_path = '/path/to/image.jpg'

# アップロードデータ
files = {'file': open(image_path, 'rb')}

# POSTリクエストで画像をアップロード
response = requests.post(media_endpoint, files=files)

# レスポンスのJSONデータを取得
media = response.json()

# アップロードした画像のメディアIDを取得
media_id = media['id']

画像ファイルのパスを設定し、https://your-site.com/wp-json/wp/v2/mediaへPOSTリクエストで送信します。media_id = media[‘id’]でメディアIDを取得可能です。

アップロードする画像ファイルのパスは、image_path変数に適切なパスを指定してください。

基本的に事前に調べたカテゴリやタグを使用したり、アイキャッチ画像はアップロード済みの物を使用すればコードが短く済みますが、全てをまとめて実行する場合、下記のコードの様になります。

import requests

# WordPressのREST APIのエンドポイント(カテゴリ)
category_endpoint = 'https://your-site.com/wp-json/wp/v2/categories'

# WordPressのREST APIのエンドポイント(タグ)
tag_endpoint = 'https://your-site.com/wp-json/wp/v2/tags'

# WordPressのREST APIのエンドポイント(記事)
post_endpoint = 'https://your-site.com/wp-json/wp/v2/posts'

# カテゴリ名とタグ名
category_name = 'カテゴリ名'
tag_name = 'タグ名'

# タイトル、本文、画像ファイルのパス
title = '投稿のタイトル'
content = '投稿の内容'
image_path = '/path/to/image.jpg'

# カテゴリIDとタグIDの初期値を設定
category_id = None
tag_id = None

# カテゴリIDを取得
response = requests.get(category_endpoint)
categories = response.json()
for category in categories:
    if category['name'] == category_name:
        category_id = category['id']
        break

# タグIDを取得
response = requests.get(tag_endpoint)
tags = response.json()
for tag in tags:
    if tag['name'] == tag_name:
        tag_id = tag['id']
        break

# カテゴリとタグのIDが取得できなかった場合は終了
if category_id is None or tag_id is None:
    print('カテゴリまたはタグが見つかりませんでした。')
    exit()

# アップロードする画像ファイルのデータ
files = {'file': open(image_path, 'rb')}

# 画像をアップロード
response = requests.post(media_endpoint, files=files)
media = response.json()
media_id = media['id']

# 記事データ
data = {
    'title': title,
    'content': content,
    'status': 'publish',
    'categories': [category_id],
    'tags': [tag_id],
    'featured_media': media_id
}

# 記事を投稿
response = requests.post(post_endpoint, json=data)
post = response.json()

# 投稿のIDを表示
print('投稿が作成されました。ID:', post['id'])

最初にカテゴリとタグのIDを取得し、その後にアイキャッチ画像をアップロードして記事を投稿しています。カテゴリ名とタグ名を指定し、それに対応するIDを取得する処理が含まれています。

注意点
  1. https://your-site.com/wp-json/wp/v2/categories:WordPressのカテゴリのエンドポイント。自分のWordPressサイトのURLを使用してください。
  2. https://your-site.com/wp-json/wp/v2/tags:WordPressのタグのエンドポイント。自分のWordPressサイトのURLを使用してください。
  3. 投稿のタイトル:投稿する記事のタイトルを指定してください。
  4. 投稿の内容:投稿する記事の本文を指定してください。
  5. /path/to/image.jpg:アップロードする画像ファイルのパスを指定してください。

WordPress REST APIの一部の主要なエンドポイントを書いておきますので、参考にしてください。

  1. 投稿関連のエンドポイント:
    • /wp/v2/posts: 投稿の作成、取得、更新、削除などの操作を行います。
    • /wp/v2/categories: カテゴリの作成、取得、更新、削除などの操作を行います。
    • /wp/v2/tags: タグの作成、取得、更新、削除などの操作を行います。
    • /wp/v2/media: メディア(画像や動画)のアップロード、取得、更新、削除などの操作を行います。
  2. ユーザー関連のエンドポイント:
    • /wp/v2/users: ユーザーの作成、取得、更新、削除などの操作を行います。
    • /wp/v2/users/me: 現在のユーザーの情報を取得します。
  3. カスタム投稿タイプ関連のエンドポイント:
    • /wp/v2/{post_type}: カスタム投稿タイプに関する操作を行います。
  4. コメント関連のエンドポイント:
    • /wp/v2/comments: コメントの作成、取得、更新、削除などの操作を行います。
  5. カスタムエンドポイント:
    • サイトに独自のエンドポイントを追加して、カスタムな操作やデータの取得を行うことも可能です。

チャットGPTで記事を作り自動投稿する

ここまでの解説でWordpressへ投稿する処理は理解できたと思います。
後は前回作成した、makeBlog.pyにこの内容を合わせれば完成です。

一応、全部まとめたコードを記載します。本来はファイルを分割したり関数にまとめたりしますが、Pythonを触ったことがない方でも、理解しやすいように1ファイルにしてあります。

import openai
import requests
from requests.auth import HTTPBasicAuth

openai.api_key = "sk-<your secret key>" # 取得したAPIキーを入力

# openAIへAPIリクエストを投げて、レスポンスを返却するクラス
def getOpenAIResponse(question):
    response = openai.Completion.create(
        model="text-davinci-003",
        prompt=question,
        max_tokens=1000,
        echo=False
    )
    
    response_text = response['choices'][0]['text'].replace('\n', '')
 
    return response_text

# HTMLでフォーマット
class HtmlFormat:
    # 各プロパティの初期化処理
    def __init__(self, item, request, response, html_format, open_api_flg):
        self.item = item
        self.request = request
        self.response = response
        self.html_format = html_format
        self.open_api_flg = open_api_flg
        
    # HTMLでフォーマット   
    def getFormatContent(self):
        if (self.item != "タイトル"):
            return f"<{self.html_format}>{self.response}</{self.html_format}>"
        else:
            return self.response
        

# main
title = "" # タイトル保存
solution_1 = "" # 方法1を保存
solution_2 = "" # 方法2を保存

# リクエスト配列 - 記事の構成をお好きな形に変更して下さい。
html_format_list = [
    HtmlFormat("タイトル", "ダイエットのブログタイトルを1つ考えて下さい。語尾は「方法」でお願いします。", "", "", True),
    HtmlFormat("リード文のタイトル", "", "はじめに", "h2", False),
    HtmlFormat("リード文", "のリード文を考えて下さい。", "", "p", True),
    HtmlFormat("2つの方法", "", "2つの方法", "h2", False),
    HtmlFormat("方法1", "のやり方を箇条書きで10文字以下で1つ考えて下さい。", "", "h3", True),
    HtmlFormat("方法1詳細", "の詳細を100文字以上で教えて下さい。", "", "p", True),
    HtmlFormat("方法2", "のやり方を箇条書きで10文字以下で1つ考えて下さい。", "", "h3", True),
    HtmlFormat("方法2詳細", "の詳細を100文字以上で教えて下さい。", "", "p", True),
    HtmlFormat("まとめタイトル", "", "まとめ", "h2", False),
    HtmlFormat("まとめ", "の結論を200文字以上で教えて下さい。", "1", "p", True)
]

# 項目ごとにリクエスト内容を変更するので、ラムダを使用して変換
request_dic = {"タイトル": lambda x:x.request, 
               "リード文": lambda x:title + x.request,
               "方法1": lambda x:title + x.request,
               "方法1詳細": lambda x:solution_1 + x.request,
               "方法2": lambda x:solution_1 + "以外で" + title + x.request,
               "方法2詳細":lambda x:solution_2 + x.request,
               "まとめ": lambda x:title + x.request
            }

for html_format in html_format_list:
    while True:
        if html_format.open_api_flg:
            html_format.request = request_dic[html_format.item](html_format) 
            html_format.response = getOpenAIResponse(html_format.request)
        if html_format.item == "タイトル":
            title = html_format.response
        elif html_format.item == "方法1":
            solution_1 = html_format.response
        elif html_format.item == "方法2":
            solution_2 = html_format.response
                
        if html_format.response is None:
            print("リクエストに失敗しました。再実行します。")
        else:
            break
        
# 記事をひとまとめにする
contents = ''       
for html_format in html_format_list:
    contents += html_format.getFormatContent()
    

# 認証情報
username = '<your name>' # wordpress のユーザー名
password = '<your password>' # アプリケーションパスワード

# WordPressのREST APIのエンドポイント 自分のドメインに置き換えてください。
endpoint = 'https://your-site.com/wp-json/wp/v2/posts'

# 下書きとして投稿するデータ
data = {
    'title': title,
    'content': contents,
    'status': 'draft'  # 下書きステータス
}

# POSTリクエストで下書き投稿
response = requests.post(endpoint, json=data, auth=(username, password))
print(response)

# レスポンスのJSONデータを取得
post = response.json()

# 投稿のIDを表示
print('下書きが作成されました。ID:', post['id'])

ご自身の環境に合わせて修正し、実行してください。

python makeBlog.py

# -- 以下出力 --
<Response [201]>
下書きが作成されました。ID: 393

この様に出力されWordpressの管理画面を確認すると、画像の様に記事の下書きができているかと思います。

如何でしたか?分からない部分があれば、いつでもご質問ください。

スケジュール化する

最後は、定期実行できる様にスケジュールで実行できる様にしましょう。定期実行の方法は、LinuxならCRON、Windowsならタスクスケジューラに登録することで可能です。それぞれ設定を

CRON

CRONは、Unix/Linux系のOSで定期的なタスクをスケジュール設定によって自動実行できます。
Pythonスクリプトを定期実行する場合、以下の手順で設定します。

1、Pythonのパスを下記コマンドで調べます。(which python)

which python

# -- 以下出力 --
/usr/local/opt/python@3.10/bin/python

上記は私が実行した場合に出力されたパスです。実行環境により異なります。

2、ターミナルを開き、crontab -eコマンドを実行してcronの設定ファイルを開きます。

crontab -e

エディタが開かれるので、実行したいPythonスクリプトを追加します。以下は、スクリプトを毎日午前9時に実行する例です。

設定ファイルは下記の様に記述します。

分 時 日 月 曜日 実行プログラムのパス 実行ファイルのパス
0 9 * * * /usr/local/opt/python@3.10/bin/python /path/to/makeBlog.py

分、時、日、月、曜日はそれぞれ次のように指定します。

項目設定値
0〜59
0〜23
1〜31
1〜12
曜日0〜7(0,7=日曜、1=月曜、2=火曜、3=水曜、4=木曜、5=金曜、6=土曜)

これで毎朝9時に自動的にチャットGPTからブログ記事が作成され、Wordpressへ自動的に投稿されます

タスクスケジューラー

タスクスケジューラとはWindowsに標準搭載されているタスク管理アプリケーションです。
特定の曜日や時間で指定したアプリケーション(スクリプト)を定期的に実行することができます。

タスクスケジューラを使ってPythonを実行するために、事前に確認しておくことは下記の2つです。

  1. Pythonの実行ファイルの存在するパス名
  2. 実行させたいPythonスクリプトの存在するフォルダ名、ファイル名

Pythonの実行ファイルの存在するパスを確認する方法は、環境変数に設定されているpathの中に、Pythonの実行ファイルが存在する場所を確認します。具体的には下記の様に調べます。

  1. 「スタート」メニューの「Windowsシステムツール」から、「コントロールパネル」を選択します。
  2. コントロールパネル」画面より、「システムとセキュリティ」を選択します。
  3. システムとセキュリティ」画面にて、「システム」を選択します。
  4. 詳細情報」にて、「システムの詳細設定」を選択します。
  5. システムのプロパティ」画面の「詳細設定」タブで、「環境変数」を選択します。
  6. 環境変数」画面の「Path」を選択し、「編集」を選択します。
  7. Pathをコピーしておきます。

次に、タスクスケジューラを起動して、設定していきます。

  1. スタート」メニューの「Windows管理ツール」から、「タスクスケジューラ」を選択します。
  2. タスクスケジューラ」画面のメニューより、「操作」を選択し、「基本タスクの作成」を選択します。
  3. 「基本タスクの作成」画面で、
    • 名前」:実行する処理の名前を設定
    • 説明:実行する処理の説明を設定
    • 入力が完了したら、「次へ」を選択します。
  4. トリガー」画面では、このタスクがどんな頻度で実行されるのかを選択することができます。今回は、「毎日」実行させるため、「毎日」を選択します。頻度の選択が完了したら、「次へ」を選択します。後は下記の様に時間と間隔を設定します。

プログラムの開始」画面では、下記の3つを設定します。

  1. プログラム/スクリプト:Pythonの実行ファイルをフルパスを設定
  2. 引数の追加:Pythonスクリプトのファイル名を設定
  3. 開始:実行させたいPythonスクリプトの存在するフォルダ名を設定

設定完了したら、「次へ」を選択します。

これでWindowsでの自動実行の設定が完了しました。

まとめ

本当はこの記事でチュートリアルを終わりにするつもりでしたが、まだ設定ファイルの分離や、何についてのブログを書くかを変更する方法の解説が終わっていませんので、おまけとして次回の記事にまとめます。(ちょっと長くなりすぎたので、別記事にさせてください。)

ここまでの解説で続きの部分が作れそうな方は、是非、ご自身でカスタマイズして見てください。

チャットGPTで作成した記事は、オリジナリティが無くグーグルからの評価に弱いとかSEO的にダメだという記事を見かける事はありますが、全然そんな事はありません。しっかりした構成を検討し、自動生成させる事で収益化できている方は大勢います。当然、アドセンスの審査も通ります。

便利なものは、どんどん取り入れて作業を効率化する事は、今後の社会生活において必須になります。

皆さんがこのチュートリアルをきっかけに素晴らしいサービスを創られることを楽しみにしています。