PythonでWordPress自動投稿ツールを作る!AI記事作成からアップロードまで

GeminiとWordPressを繋ぐ!AI自動投稿GUIツールのPythonコードを徹底解説

ブログ運営において、記事の執筆、画像作成、投稿といった一連の作業は多くの時間を要します。もし、AIが生成した魅力的なコンテンツを、手間なくWordPressに公開できたら、どれほど効率化できるでしょうか?

今回解説するPythonのプログラムコードは、まさにその「AIによるコンテンツ生成からWordPressへの自動投稿」までを一気通貫で行うためのGUIツールです。Googleの先進的なAIであるGeminiを使って記事のタイトル、メタディスクリプション、本文を生成し、さらにはアイキャッチ画像まで自動生成・設定して、WordPressに投稿する機能をGUI(グラフィカルユーザーインターフェース)上で提供します。

この記事では、提供されたPythonコードを深掘りし、その仕組み、使われている技術、そしてどのように活用できるのかを初心者にも分かりやすく解説します。

目次

このコードが解決する課題とツールの目的

提供されたPythonコードは、以下のような課題を解決し、ブログ運営の効率化を目指しています。

  1. コンテンツ生成の手間: ブログ記事のタイトル、導入文、本文構成などを考えるのは時間がかかります。
  2. SEO要素の最適化: 読者の目に留まりやすいタイトルや、検索エンジンの評価につながるメタディスクリプションを考えるのは難しい場合があります。
  3. アイキャッチ画像作成: 記事の内容に合った魅力的な画像を都度作成するのは大変です。
  4. WordPressへの投稿作業: コンテンツのコピペ、画像のアップロードと設定、各種設定(メタディスクリプションなど)は定型作業であり、自動化の余地があります。

このツールは、ユーザーが簡単な指示(元となるテキストや質問)を入力するだけで、AIがこれらの要素を生成し、さらに自動でWordPressに投稿する機能を提供します。特に、GUIインターフェースを備えているため、コマンドライン操作に不慣れな方でも直感的に利用できるのが大きなメリットです。

主要な機能とコードのロジック解説

コードはいくつかの主要な機能ブロックに分けることができます。それぞれがどのように連携して動作するのかを見ていきましょう。

1. 設定の読み込みとAPIの初期化

コードの冒頭部分では、必要なライブラリをインポートし、設定情報を読み込んでいます。

import os
import json
import time
from datetime import datetime
import requests
from dotenv import load_dotenv
import random
import textwrap

# ... GUI and AI libs ...

load_dotenv(dotenv_path="apikey.env")

WP_URL = os.getenv("WP_URL")
WP_USERNAME = os.getenv("WP_USERNAME")
WP_APP_PASSWORD = os.getenv("WP_APP_PASSWORD")
GEMINI_API_KEY = os.getenv("GEMINI_API_KEY")
META_DESCRIPTION_FIELD_KEY = os.getenv("META_DESCRIPTION_FIELD_KEY", "_aioseo_description")
GEMINI_MODEL_NAME = os.getenv("GEMINI_MODEL_NAME", 'gemini-1.5-flash-latest')

# ... other constants ...

def configure_gemini():
    global gemini_model
    if not GEMINI_API_KEY: log_message("エラー: Gemini APIキー未設定。"); return False
    try:
        genai.configure(api_key=GEMINI_API_KEY)
        gemini_model = genai.GenerativeModel(GEMINI_MODEL_NAME)
        log_message(f"Gemini API初期化成功 (モデル: {GEMINI_MODEL_NAME})。"); return True
    except Exception as e: log_message(f"エラー: Gemini API初期化失敗: {e}"); gemini_model = None; return False
  • load_dotenv: これは .env ファイルから環境変数を読み込むための標準的な方法です。APIキーやWordPressのログイン情報など、機密性の高い情報をコードに直接書き込まずに管理できます。これはセキュリティの観点からも非常に重要です。
  • configure_gemini(): 読み込んだGemini APIキーを使って、Google Generative AIライブラリを初期化します。APIキーが設定されていない場合や初期化に失敗した場合は、エラーメッセージをログに出力し、処理を中断します。

2. Gemini APIによるコンテンツ生成

このツールの核となる部分の一つが、Geminiを使ったコンテンツ生成機能です。タイトル、メタディスクリプション、本文それぞれに対応した関数が用意されています。

# --- ★★★ プロンプト修正 (余計な応答抑制強化) ★★★ ---
def generate_title_with_gemini(text_input):
    # ... prompt definition ...
    try:
        # ... API call and response processing ...
    except Exception as e:
        # ... error handling ...

# --- ★★★ プロンプト修正 (余計な応答抑制強化) ★★★ ---
def generate_metadesc_with_gemini(text_input, article_title=""):
    # ... prompt definition ...
    try:
        # ... API call and response processing ...
    except Exception as e:
        # ... error handling ...

# --- ★★★ プロンプト修正 (余計な応答抑制強化) ★★★ ---
def generate_content_with_gemini(text_input, input_type="general"):
    # ... prompt definition ...
    try:
        # ... API call and response processing ...
    except Exception as e:
        # ... error handling ...
  • 各関数は、ユーザーからの入力テキストや生成したいコンテンツの種類に応じて、詳細なプロンプトを作成しています。プロンプトには、AIにどのような役割(プロのブロガー、SEOエキスパートなど)を演じさせ、どのような形式(Markdown、タイトルリストなど)で出力させるかの指示が含まれています。特に、「余計な応答を抑制強化」とコメントされていることから、期待する出力形式を厳密に指示するためにプロンプトが調整されていることが分かります。
  • gemini_model.generate_content() を呼び出すことで、実際にGemini APIにリクエストを送信し、生成されたテキストを取得します。
  • API呼び出しは try...except ブロックで囲まれており、エラーが発生した場合の処理(ログ出力、空値の返却など)が行われます。

3. アイキャッチ画像の自動生成

Pillowライブラリを使用し、生成された記事タイトルをもとに簡単なアイキャッチ画像を生成します。

try:
    from PIL import Image, ImageDraw, ImageFont
    PILLOW_AVAILABLE = True
except ImportError:
    PILLOW_AVAILABLE = False
    # ... warning message ...

# ... get_random_base_image_path, get_font_path_absolute functions ...

def create_eyecatch_image(title_text, output_filename_base="eyecatch"):
    if not PILLOW_AVAILABLE: return None

    base_image_path = get_random_base_image_path()
    font_path_abs = get_font_path_absolute()

    if not base_image_path or not font_path_abs: return None

    try:
        img = Image.open(base_image_path).convert("RGBA")
        draw = ImageDraw.Draw(img)
        img_width, img_height = img.size

        # テキストのラッピングとフォントサイズ調整ロジック
        # ... (ループ処理で最適なサイズを見つける) ...

        # テキストの描画 (輪郭と本体)
        # ... (draw.text 関数を使用) ...

        # 画像の保存
        # ... (フォルダ作成、ユニークなファイル名生成、img.save) ...

        return saved_image_path

    except Exception as e:
        # ... error handling ...
  • PILLOW_AVAILABLE フラグで、Pillowがインストールされているかを確認しています。インストールされていない場合は機能が無効化されます。
  • あらかじめ用意されたベース画像の中からランダムに1枚を選び、その画像の上に記事タイトルを重ねて描画します。
  • タイトルの文字列が画像の幅に収まるように自動で折り返し (textwrap.wrap)、さらに画像の高さに収まるようにフォントサイズを調整するロジックが含まれています。
  • テキストは、読みやすさを向上させるために輪郭線付きで描画されています。
  • 生成された画像は、指定されたフォルダにユニークなファイル名で保存されます。

4. WordPress REST APIによる投稿

生成されたコンテンツと画像をWordPressに送信し、記事として公開します。

def upload_image_to_wordpress(image_path, title=""):
    if not all([WP_URL, WP_USERNAME, WP_APP_PASSWORD]): return None

    media_url = f"{WP_URL.rstrip('/')}/wp-json/wp/v2/media"

    try:
        # ファイルを開いてrequests.postで送信
        with open(image_path, 'rb') as img_file:
            files = {'file': (filename, img_file, content_type)}
            data = {} # title, captionなどを設定
            # ... requests.post call with auth and files ...
            response.raise_for_status()
            # ... process response to get media ID ...
            return media_id
    except requests.exceptions.RequestException as e:
        # ... error handling ...

def create_wordpress_post(title, content_html, metadescription=None, featured_media_id=None):
    if not all([WP_URL, WP_USERNAME, WP_APP_PASSWORD]): return None

    api_url = f"{WP_URL.rstrip('/')}/wp-json/wp/v2/posts"
    headers = {"Content-Type": "application/json"}

    post_data = {
        "title": title,
        "content": content_html,
        "status": "publish" # または "draft"
    }

    if metadescription and META_DESCRIPTION_FIELD_KEY:
        post_data["meta"] = { META_DESCRIPTION_FIELD_KEY: metadescription }

    if featured_media_id:
        post_data["featured_media"] = featured_media_id

    try:
        # JSONデータをrequests.postで送信
        # ... requests.post call with auth and json ...
        response.raise_for_status()
        # ... process response to get post ID and link ...
        return post_id, post_link
    except requests.exceptions.RequestException as e:
        # ... error handling ...
  • requests ライブラリを使用して、WordPressのREST APIエンドポイントにHTTPリクエストを送信します。
  • upload_image_to_wordpress 関数は、生成された画像ファイルをWordPressのメディアライブラリにアップロードし、そのメディアIDを取得します。認証にはユーザー名とアプリケーションパスワードを使用します。
  • create_wordpress_post 関数は、タイトル、HTML形式に変換された本文、メタディスクリプション、そしてアップロード済みのアイキャッチ画像IDを含むペイロードを作成し、WordPressの投稿エンドポイントに送信します。status: "publish" と設定することで、即時公開されます(必要であれば "draft" に変更可能)。
  • ここでも try...except ブロックと response.raise_for_status() を使って、通信エラーやAPIからのエラー応答(HTTPエラー)を検知し、適切にログ出力しています。

5. MarkdownからHTMLへの変換

Geminiが生成した本文はMarkdown形式で取得されますが、WordPressのREST APIに投稿する際はHTML形式が適しています。

try:
    import markdown
    from markdown.extensions.codehilite import CodeHiliteExtension
    from markdown.extensions.fenced_code import FencedCodeExtension
    MARKDOWN_AVAILABLE = True
except ImportError:
    MARKDOWN_AVAILABLE = False

# ... inside post_to_wordpress_action_gui and generate_and_post_action ...
if MARKDOWN_AVAILABLE:
    try:
        content_html = markdown.markdown(
            content_markdown,
            extensions=[
                FencedCodeExtension(),
                CodeHiliteExtension(linenums=False, css_class='highlight')
            ]
        )
        log_message("MarkdownをHTMLに変換しました (Pygments使用)。")
    except Exception as e:
        log_message(f"MarkdownからHTMLへの変換中にエラーが発生しました: {e}。基本的な変換を試みます。")
        content_html = markdown.markdown(content_markdown)
else:
    log_message("Markdownライブラリが無いため、基本的な改行置換のみ行います。")
    content_html = content_markdown.replace("\n", "<br />\n")
  • python-markdown ライブラリを使用して、MarkdownテキストをHTMLに変換します。
  • FencedCodeExtension は、バッククォートで囲まれたコードブロックを正しく解釈するために使用されます。
  • CodeHiliteExtension は、コードブロックにシンタックスハイライト(色付け)を適用するために使用されます。これには通常、Pygmentsライブラリが必要です。
  • これらのライブラリが利用できない場合でも、最低限の変換(改行を <br> に変換)を行うフォールバック処理が実装されています。

6. GUIインターフェース (Tkinter)

ユーザーがコードを操作するためのGUIは、Python標準ライブラリであるTkinterを使って構築されています。

import tkinter as tk
from tkinter import scrolledtext, messagebox, ttk, font as tkfont

class GeminiWordPressPosterApp:
    def __init__(self, root_tk):
        # ... GUI element creation (Frames, Labels, Entries, Buttons, ScrolledText) ...
        # ... Layout management (pack) ...
        # ... Event binding (e.g., button commands, text modification trace) ...
        # ... Status labels and message boxes ...

    def generate_all_article_elements_action(self): # ボタン押下時の処理
        # ... gets input from GUI ...
        # ... calls Gemini generation functions ...
        # ... sets generated content to GUI elements ...
        # ... toggles button states ...

    def generate_eyecatch_action_gui(self): # ボタン押下時の処理
        # ... gets title from GUI ...
        # ... calls create_eyecatch_image ...
        # ... updates status label ...

    def post_to_wordpress_action_gui(self): # ボタン押下時の処理
        # ... gets content from GUI ...
        # ... converts markdown to html ...
        # ... calls upload_image_to_wordpress if needed ...
        # ... calls create_wordpress_post ...
        # ... displays result message ...
        # ... offers to clear fields ...
        # ... toggles button states ...

    def generate_and_post_action(self): # ボタン押下時の処理 (一括)
        # ... sequence of generate title, meta, content, eyecatch, upload image, create post ...
        # ... error handling at each step ...
        # ... updates GUI and logs ...

    def log_to_gui(self, message):
        # ... inserts message into scrolledtext widget ...

    # ... other helper methods (update char counts, check configs, etc.) ...

if __name__ == "__main__":
    root = tk.Tk()
    app = GeminiWordPressPosterApp(root)
    root.mainloop()
  • tkinter.Tk でメインウィンドウを作成します。
  • ttk (Themed Tkinter) を使用することで、より現代的なルック&フィールを実現しています。
  • scrolledtext.ScrolledText は、スクロール可能な複数行テキスト入力・表示エリアを提供します。
  • ボタン (ttk.Button) の command オプションに、クリック時に実行されるメソッドを指定することで、ユーザーのアクションに応じた処理を実装しています。
  • StringVar を使用して、エントリーウィジェットとPythonコードの間でテキストデータを簡単に連携させています。
  • trace_add("write", ...) は、テキストが変更されたイベントを捕捉し、文字数カウントを更新するために使われています。
  • messagebox を使用して、警告やエラー、成功メッセージなどをユーザーに表示します。
  • log_to_gui メソッドにより、コマンドラインだけでなくGUI上のログエリアにもメッセージが表示されるようになっています。
  • ボタンの状態を切り替える (_toggle_buttons_state_gui) ことで、処理中はユーザー操作を受け付けないようにしています。

7. ロギング機能

処理の状況、成功、警告、エラーなどを記録するためのシンプルなロギング機能が実装されています。

LOG_FILE = "gemini_wp_poster_v1.3_batch.log"

def log_message(message):
    timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    log_entry = f"[{timestamp}] {message}\n"
    print(log_entry.strip()) # コンソールにも出力
    if app_instance and hasattr(app_instance, 'log_to_gui') and app_instance.root and app_instance.root.winfo_exists():
        try: app_instance.log_to_gui(log_entry) # GUIにも出力
        except tk.TclError: pass
    try:
        with open(LOG_FILE, "a", encoding="utf-8") as f: f.write(log_entry) # ファイルにも出力
    except Exception as e: print(f"ログファイル書き込みエラー: {e}")
  • log_message 関数は、タイムスタンプを追加したメッセージをコンソール、GUIのログエリア、そして指定されたログファイルに同時に出力します。これにより、ツールの動作状況や問題発生時の原因特定が容易になります。

使用されている技術・ライブラリの詳細

このツールは、Pythonエコシステムの多様なライブラリを組み合わせて構築されています。

  • Python: プログラミング言語そのものです。豊富なライブラリと比較的高い可読性から、このような多様なタスクを組み合わせるアプリケーション開発に適しています。
  • Google Generative AI (google-generativeai): Googleが提供するGeminiなどの生成AIモデルにアクセスするための公式Pythonライブラリです。テキスト生成機能のバックエンドとして機能します。
  • Requests (requests): PythonでHTTPリクエストを行うためのデファクトスタンダードライブラリです。WordPress REST APIとの通信に使用されています。非常に使いやすく、複雑なAPI連携もシンプルに記述できます。
  • python-dotenv (python-dotenv): .env ファイル形式で記述された設定情報を、Pythonスクリプトから環境変数として読み込めるようにするライブラリです。APIキーやパスワードなどの機密情報を安全に管理するために不可欠です。
  • Pillow (Pillow): 画像処理を行うための強力なライブラリです。アイキャッチ画像の生成、テキスト描画、画像形式の変換などに使用されています。
  • python-markdown (markdown) & Pygments (Pygments): Markdown形式のテキストをHTMLに変換するためのライブラリです。特にPygmentsと連携することで、コードブロックのシンタックスハイライトも可能になり、技術記事の見栄えを向上させます。
  • Tkinter: Python標準ライブラリに含まれるGUIツールキットです。外部ライブラリのインストールなしにGUIアプリケーションを作成できます。tkinter.ttk を使うことで、OS標準に近いウィジェットやテーマを利用できます。

これらのライブラリを組み合わせることで、AI、画像処理、Web API通信、GUIといった異なる分野の技術を一つのアプリケーションとして実現しています。

セットアップと実行方法

このツールを使用するには、いくつかの準備が必要です。

1. Pythonのインストール

Python 3.7以上のバージョンが必要です。公式ウェブサイトからダウンロードしてインストールしてください。
Python公式ウェブサイト

2. 必要なライブラリのインストール

コマンドプロンプトやターミナルを開き、以下のコマンドを実行して必要なライブラリをインストールします。仮想環境を作成してインストールすることを強く推奨します。

# 仮想環境の作成 (推奨)
python -m venv venv
# 仮想環境のアクティベート (Windows)
# venv\Scripts\activate
# 仮想環境のアクティベート (macOS/Linux)
# source venv/bin/activate

# 必要なライブラリのインストール
pip install python-dotenv google-generativeai requests Pillow markdown Pygments

3. .env ファイルの作成

スクリプトファイルと同じディレクトリに .env という名前のファイルを作成し、以下の内容を記述します。= の右側には、それぞれの情報を設定してください。

# WordPress Settings
WP_URL="あなたのWordPressサイトのURL (例: https://your-blog.com)"
WP_USERNAME="WordPressのユーザー名"
WP_APP_PASSWORD="WordPressのアプリケーションパスワード" # WP管理画面で生成

# Google Gemini API Key
GEMINI_API_KEY="あなたのGemini APIキー" # Google AI Studioなどで取得

# WordPress Meta Description Field Key (Optional, for SEO plugins like AIOSEO)
# 使用しているSEOプラグインのメタディスクリプション用カスタムフィールド名を指定。
# 不明な場合や不要な場合はコメントアウトするか、空にしてください。
# AIOSEOの場合のデフォルト値: _aioseo_description
META_DESCRIPTION_FIELD_KEY="_aioseo_description"

# Gemini Model Name (Optional, default is gemini-1.5-flash-latest)
# 必要に応じて使用するモデル名を変更できます。
GEMINI_MODEL_NAME="gemini-1.5-flash-latest"

4. ベース画像フォルダとフォントファイルの準備

  • スクリプトファイルと同じディレクトリに png という名前のフォルダを作成し、アイキャッチ画像のベースとして使用したいPNGまたはJPG画像をいくつか配置します。
  • スクリプトファイルと同じディレクトリに font という名前のフォルダを作成し、使用したいフォントファイル(例: .ttf, .otf)を配置します。コード中の RELATIVE_FONT_PATH 定数(デフォルトは "font/Corporate-Logo-Bold-ver3.otf")を、実際に配置したフォントファイルのパスに合わせて修正してください。商用利用可能なフォントを使用するように注意してください。

5. スクリプトの実行

上記準備が完了したら、コマンドプロンプトやターミナルでスクリプトファイルがあるディレクトリに移動し、以下のコマンドでスクリプトを実行します。

python your_script_name.py # your_script_name.py はスクリプトのファイル名

GUIウィンドウが表示されるので、テキストを入力し、タイプを選択して、生成・投稿ボタンをクリックすることでツールを利用できます。

使用例・応用例

このツールは、以下のような様々なシーンで活用できます。

  • 通常ブログ記事の作成: 特定のトピックに関する情報をInputテキストとして与え、「一般的なテキスト」タイプで生成すれば、構造化された記事のドラフトを得られます。
  • Q&A形式記事の作成: 読者からよくある質問や、解説したい疑問点をInputテキストとして与え、「ユーザーからの質問」タイプを選択すれば、質問に直接答える形式の記事を作成できます。
  • 技術解説記事の作成: プログラムコードや技術仕様に関するテキストまたはコード自体をInputに入れ、「プログラムコード解説」タイプを選択すれば、コードブロックを含む解説記事を生成できます。
  • 下書きとしての利用: 「タイトル・メタ・本文を生成 (編集用)」ボタンを使えば、即時投稿せずにAIが生成した内容をGUI上で確認・編集できます。これにより、AIの生成結果をベースにしながら、人間の手による微調整を加えて品質を高めることが可能です。
  • バッチ処理への発展: 現在はGUIツールですが、コアとなるGemini連携関数やWordPress投稿関数はGUIから独立しています。これらの関数を直接呼び出すスクリプトを作成すれば、複数の入力テキストファイルをまとめて処理し、自動で大量の記事を投稿するバッチ処理ツールに応用することも可能です(ただし、その場合はエラー処理やAPIレート制限への考慮がより重要になります)。

学習者向けのポイント・発展的なトピック

このコードは、Pythonを使った実践的なアプリケーション開発の良い学習材料となります。

学習できるポイント

  • API連携: Google Gemini APIとWordPress REST APIという二つの異なるWeb APIとの連携方法を具体的に学べます。HTTPリクエストの送信、認証、JSONデータの送受信といった基本的なAPI操作が詰まっています。
  • GUIプログラミング: Tkinterを使った基本的なGUIアプリケーションの構造、ウィジェットの配置、イベント処理について学ぶことができます。
  • 外部ライブラリの活用: requests, Pillow, markdown など、様々な目的で広く使われているPythonライブラリの実践的な使い方を知ることができます。
  • 設定管理: .env ファイルを使った安全な設定情報管理の方法を理解できます。
  • エラーハンドリング: try...except ブロックを使った例外処理や、APIのエラーレスポンス処理の重要性を学ぶことができます。
  • ファイル操作: 設定ファイルやログファイル、画像ファイルの読み書きといった基本的なファイル操作も含まれています。

発展的なトピック

  • 非同期処理: 現在のコードは一部の処理(特にAPI呼び出しや画像生成)でGUIが一時的に応答しなくなる可能性があります。asyncio やスレッドを使った非同期処理を導入することで、UIの応答性を維持できます。
  • UI/UXの改善: より洗練されたGUIライブラリ(例: PyQt, Kivy)の利用や、進捗バーの表示などでユーザー体験を向上させることができます。
  • 詳細なプロンプト設計: より高品質な記事を生成するため、AIへの指示(プロンプト)をさらに洗練させる方法を探求できます。特定の文体やキーワードの指定など、高度なプロンプトエンジニアリングに挑戦できます。
  • カテゴリ・タグ・予約投稿: WordPress投稿時にカテゴリやタグを設定したり、公開日時を指定したりする機能を追加できます。
  • 別のAIモデルやCMSへの対応: Gemini以外のAIモデル(例: OpenAI API)や、WordPress以外のCMS(例: Blogger, Shopify)にも対応できるように拡張することも考えられます。

まとめ

今回解説したPythonコードは、Google Geminiの強力なコンテンツ生成能力とWordPressの柔軟な公開機能を組み合わせた、ブログ運営の効率化に役立つGUIツールです。設定ファイルの読み込み、AI連携、画像生成、そしてWeb APIによる投稿処理といった、現代のアプリケーション開発に不可欠な様々な技術要素が詰め込まれています。

この記事を通じて、コードの各部分の役割や使われている技術について理解を深められたなら幸いです。このコードをそのまま利用するだけでなく、自身のニーズに合わせてカスタマイズしたり、含まれている各技術要素をさらに深く学んだりすることで、Pythonプログラミングのスキルを大きく向上させることができるでしょう。

ぜひ実際にコードを動かしてみて、AIを活用した新しいブログワークフローを体験してみてください。そして、もし可能であれば、コードを改善したり、新しい機能を追加したりして、さらにパワフルなツールへと発展させていくことも素晴らしい挑戦となるはずです。

撮影に使用している機材【PR】

【無料】撮った写真でWEBページを作りませんか?

この記事が気に入ったら
フォローしてね!

よかったらシェアしてね!
  • URLをコピーしました!
目次