WordPress REST APIで記事投稿を爆速化:ブラウザ自動化から解放

はじめに

ブログ記事の自動投稿をブラウザ自動化(Selenium/Playwright)で実装していませんか?この記事では、WordPress REST APIを使って記事投稿を50-75分→10秒に短縮した実装を紹介します。

ブラウザ自動化の限界

Seleniumでの投稿フロー

従来のブラウザ自動化:

from selenium import webdriver

def post_with_selenium(title, content, category):
    driver = webdriver.Chrome()

    # 1. ログイン(10-15秒)
    driver.get("https://example.com/wp-admin")
    driver.find_element_by_name("log").send_keys(username)
    driver.find_element_by_name("pwd").send_keys(password)
    driver.find_element_by_id("wp-submit").click()
    time.sleep(5)

    # 2. 新規投稿ページ(5-10秒)
    driver.get("https://example.com/wp-admin/post-new.php")
    time.sleep(3)

    # 3. タイトル入力
    driver.find_element_by_id("title").send_keys(title)

    # 4. 本文入力(Block Editorは複雑)
    # ...複雑なセレクタ操作...

    # 5. カテゴリ選択
    # ...ドロップダウン操作...

    # 6. 公開ボタン(5秒)
    driver.find_element_by_class("editor-post-publish-button").click()
    time.sleep(5)

    driver.quit()

問題点:
– 1記事 = 約7-10分(ブラウザ起動・画面遷移の待ち時間)
– 6記事投稿 = 50-75分
– UI変更でスクリプト破損リスク
– ヘッドレスブラウザでもメモリ消費大

解決策:WordPress REST API

API認証

Application Passwordを使います(WordPress 5.6+)。

import requests
from requests.auth import HTTPBasicAuth

WORDPRESS_URL = "https://obaba-win.com"
USERNAME = "obaba"
APP_PASSWORD = "75OJjbLkwgml8VE0TJZ3sJA1"  # Application Password

def get_auth():
    return HTTPBasicAuth(USERNAME, APP_PASSWORD)

記事投稿

シンプルなHTTP POSTで投稿できます。

def post_article_via_api(title, content, category_id, status='publish'):
    """
    WordPress REST APIで記事投稿

    Args:
        title: 記事タイトル
        content: 記事本文(HTML可)
        category_id: カテゴリID
        status: 'publish' / 'draft'

    Returns:
        投稿ID、URL
    """
    endpoint = f"{WORDPRESS_URL}/wp-json/wp/v2/posts"

    data = {
        "title": title,
        "content": content,
        "categories": [category_id],
        "status": status
    }

    response = requests.post(
        endpoint,
        json=data,
        auth=get_auth()
    )

    if response.status_code == 201:
        post_data = response.json()
        return post_data['id'], post_data['link']
    else:
        raise Exception(f"投稿失敗: {response.status_code} - {response.text}")

カテゴリ取得

カテゴリIDはAPIで取得します。

def get_categories():
    """
    WordPressのカテゴリ一覧を取得
    """
    endpoint = f"{WORDPRESS_URL}/wp-json/wp/v2/categories"

    response = requests.get(endpoint, auth=get_auth())

    if response.status_code == 200:
        categories = response.json()
        return {cat['name']: cat['id'] for cat in categories}
    else:
        raise Exception("カテゴリ取得失敗")

# 使用例
categories = get_categories()
# {'AI・LLM': 176, 'Python': 12, 'JavaScript': 13, ...}

バッチ投稿の実装

複数記事を一括投稿

def batch_post_articles(articles):
    """
    複数記事を連続投稿

    Args:
        articles: [{'title': ..., 'content': ..., 'category': ...}, ...]

    Returns:
        投稿結果のリスト
    """
    categories = get_categories()
    results = []

    for i, article in enumerate(articles, 1):
        try:
            category_id = categories.get(article['category'])

            if not category_id:
                print(f"⚠️ カテゴリ不明: {article['category']}")
                continue

            post_id, url = post_article_via_api(
                title=article['title'],
                content=article['content'],
                category_id=category_id,
                status='publish'
            )

            results.append({
                'title': article['title'],
                'post_id': post_id,
                'url': url,
                'status': 'success'
            })

            print(f"✅ [{i}/{len(articles)}] 投稿完了: {article['title']}")

        except Exception as e:
            results.append({
                'title': article['title'],
                'status': 'failed',
                'error': str(e)
            })

            print(f"❌ [{i}/{len(articles)}] 投稿失敗: {article['title']} - {e}")

    return results

Markdownから自動変換

Markdown記事をHTMLに変換して投稿します。

import markdown

def post_markdown_article(md_file, category):
    """
    Markdownファイルを読み込んでWordPressに投稿
    """
    with open(md_file, 'r', encoding='utf-8') as f:
        md_content = f.read()

    # タイトル抽出(最初の# 見出し)
    lines = md_content.split('\n')
    title = lines[0].lstrip('#').strip()
    body = '\n'.join(lines[1:]).strip()

    # Markdown → HTML変換
    html_content = markdown.markdown(
        body,
        extensions=['fenced_code', 'tables', 'codehilite']
    )

    # 投稿
    categories = get_categories()
    category_id = categories[category]

    post_id, url = post_article_via_api(title, html_content, category_id)

    print(f"✅ 投稿完了: {title}")
    print(f"   URL: {url}")

    return post_id, url

実運用での改善

カテゴリ必須チェック

uncategorized投稿を防ぎます。

def post_article_safe(title, content, category_name):
    """
    カテゴリ必須チェック付き投稿
    """
    categories = get_categories()

    if category_name not in categories:
        raise ValueError(f"カテゴリ不明: {category_name}")

    if category_name == "uncategorized":
        raise ValueError("uncategorized への投稿は禁止")

    category_id = categories[category_name]

    return post_article_via_api(title, content, category_id)

エラーハンドリング

API制限やネットワークエラーに対応します。

import time

def post_with_retry(title, content, category_id, max_retries=3):
    """
    リトライ付き投稿
    """
    for attempt in range(1, max_retries + 1):
        try:
            return post_article_via_api(title, content, category_id)
        except Exception as e:
            if attempt == max_retries:
                raise

            print(f"⚠️ 投稿失敗(試行{attempt}/{max_retries}): {e}")
            time.sleep(2 ** attempt)  # 指数バックオフ

パフォーマンス比較

ブラウザ自動化 vs REST API

項目 Selenium REST API
1記事投稿 7-10分 1-2秒
6記事バッチ 50-75分 10秒
メモリ消費 500MB+ 10MB以下
UI変更の影響 破損リスク大 影響なし

実績

2026-03-26に6記事を一括投稿:

$ time python3 wp_auto_post_v2.py

✅ [1/6] 投稿完了: WordPress自動投稿を爆速化...
✅ [2/6] 投稿完了: スマート提案機能の実装...
✅ [3/6] 投稿完了: Google Tasks統合でタスク管理を進化...
✅ [4/6] 投稿完了: ファクトチェックをAIで自動化...
✅ [5/6] 投稿完了: Next.js 15移行ガイド...
✅ [6/6] 投稿完了: フォルダ構造ベストプラクティス...

real    0m9.847s
user    0m1.234s
sys     0m0.089s

約10秒で6記事投稿完了。従来の50-75分から99%削減

セキュリティ

Application Passwordの管理

環境変数で管理します。

# .env
WORDPRESS_URL=https://obaba-win.com
WORDPRESS_USER=obaba
WORDPRESS_APP_PASSWORD=75OJjbLkwgml8VE0TJZ3sJA1
from dotenv import load_dotenv
import os

load_dotenv()

WORDPRESS_URL = os.getenv('WORDPRESS_URL')
USERNAME = os.getenv('WORDPRESS_USER')
APP_PASSWORD = os.getenv('WORDPRESS_APP_PASSWORD')

パスワード再生成

Application Passwordは再生成可能です。

  1. WordPress管理画面 → ユーザー → プロフィール
  2. “Application Passwords” セクション
  3. 古いパスワードを削除、新規生成

まとめ

WordPress REST APIを使うことで、記事投稿を劇的に高速化できます。ブラウザ自動化の50-75分が10秒になり、メモリ消費も大幅に削減。バッチ投稿やMarkdown変換と組み合わせることで、完全自動化されたブログ運用が実現できます。

関連記事:
– AI駆動タスク自動振り分け
– OpenClaw Cronジョブ活用術
– Downloads整理・次世代版構想