【Python】RSSフィードのニュース内容を元にGPTで架空のスレッドを生成してWordPressに投稿する奴

作ったもの紹介

RSSフィードの内容を元に某匿名掲示板風の架空のスレッドをGPTで生成して、DALLEで画像生成させてアイキャッチをつけてWordpressに投稿する奴。
前回の記事「【GAS】RSSフィードから最新のニュースをWordPress へ投稿する(アイキャッチ自動生成)」は、このための前座みたいなところがあったんですね~。

(同じRSSフィードを参照しているので、自然と最新ニュース投稿と架空スレッド記事を同居させることができる)。

実際のサイトは外観ほぼ弄ってない試験作品状態ですが、以下で見れます。

最新AIニュース一覧

※僕は今回のPythonスクリプトの方は自動化してないです。(理由はGPT4のAPIは少しお高いので、手動で数をコントロールしたかったからです)。

それでは毎度のごとく、GPTに解説記事をほとんど作らせたので、それを少しいじって以下に載せておきます。
(GPTへ送るテンプレプロンプトはまだ調整中でもあるので、略してます。これはあくまで実装したスクリプトの雛形です)。

目次

言語

Python(3.8.xと3.10.xで動いた)

ライブラリ

pipかpip3しましょう。

Windows:

pip install openai feedparser requests
pip3 install openai feedparser requests

Linux/Mac:

pip install openai feedparser requests
sudo pip install openai feedparser requests
pip3 install openai feedparser requests
sudo pip3 install openai feedparser requests

これらのコマンドを実行することで、必要なライブラリをインストールすることができます。

実際のソースコード例


import os
import datetime as dt
import json
import random
from random import randint, choice
import string
import openai
import base64
import re
import feedparser
from datetime import datetime
import requests

# OpenAI APIキーを環境変数から取得
openai.api_key = os.environ.get('OPENAI_API_KEY')

# RSSフィードのURLを定義(自分で特定のRSSフィードを設定してください。
rssFeedUrls = []

allEntries = []

# RSSフィードの取得とパース
for url in rssFeedUrls:
    feed = feedparser.parse(url)
    for entry in feed.entries:
        title = entry.title
        link = entry.link
        summary = entry.summary
        published = entry.published_parsed  # 公開日時を取得
        allEntries.append({
            'title': title,
            'link': link,
            'summary': summary,
            'published': published
        })

# エントリーを公開日時でソート
sortedEntries = sorted(allEntries, key=lambda x: x['published'], reverse=True)

# 最新の20件のエントリーを選択
topEntries = sortedEntries[:20]

# エントリーの内容を出力
for entry in topEntries:
    print(f"Title: {entry['title']}")
    print(f"Summary: {entry['summary']}")
    print(f"Link: {entry['link']}")
    print("-" * 50)

# ランダムに1つのエントリーを選択
randomEntry = random.choice(topEntries)

# 選択したエントリーのタイトル、サマリー、リンクを保存
selected_title = randomEntry['title']
selected_summary = randomEntry['summary']
selected_link = randomEntry['link']

# タイトルと概要を整えるためのGPT3.5-turbo用プロンプト
adjust_prompt = f'以下のRSSFeedのtitleとsummaryから、ニュースの全体の内容を推測して補完し、「ニュースタイトル:ニュース概要」の形式で出力してください。\nTitle: {selected_title}\nSummary: {selected_summary}'

# この adjust_prompt を後で OpenAI API に送信する

# プロンプトを送信してタイトルと概要を整える
adj_response = openai.ChatCompletion.create(
    model="gpt-3.5-turbo",
    messages=[
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": adjust_prompt}
    ],
    max_tokens=1000
)

# 整えられたタイトルと概要を取得
adj_title_summary = adj_response["choices"][0]["message"]["content"].strip()

# 整えられたタイトルと概要を出力
print("Adjusted Title and Summary:")
print(adj_title_summary)

# GPTにベースタイトルを作成させるためのsystemプロンプト
basetitle_prompt = f'ニュース内容を(省略。自分でうまく設定してください。)'

# スレッドタイトルのベース作成
basetitle_response = openai.ChatCompletion.create(model="gpt-4", messages=[{"role": "system", "content": basetitle_prompt}, {"role": "user", "content": adj_title_summary}], max_tokens=1000)
basetitle = basetitle_response["choices"][0]["message"]["content"].strip()

# スレッドタイトルの作成
thread_title = f"{basetitle}"

# スレッドタイトルの出力
print(thread_title)

# 書き込み数をランダムに設定(24から32の範囲で,2500tokenくらい)
num_posts = random.randint(24, 32)

# テンプレートとなる文字列
template = "{thread_title}\n"
first_post_template = "1 :架空の匿名さん@GPT:{dateTime} ID:{id}\nURL:{selected_link}\n本文:{text}\n意見:[キャラクター1の投稿内容]\n"
post_template = "{idx} :架空の匿名さん@GPT:{dateTime} ID:{id}\n[キャラクター{idx}の投稿内容]\n"
for i in range(1, num_posts + 1):
    template += post_template

# ここでthread_titleの値でtemplate内の{thread_title}を置き換える
template = template.replace('{thread_title}', thread_title)

#ランダムなIDを生成
def generate_id():
    # 5-character string composed of random digits and uppercase and lowercase letters, followed by either 'M' or '0' (0 being more frequent)
    id_base = ''.join([choice(string.ascii_letters + string.digits) for num in range(5)])
    id_end = choice(['M'] + ['0']*9)  # Choose from 10 instances (0 appearing 9 times, M appearing once)
    return id_base + id_end

def generate_datetime(current):
    # 次の投稿までの適当な時間(秒)を加算する例
    return current + dt.timedelta(seconds=randint(60, 300))

# 現在の日付と時間を取得し、その160分前を初期時間とする
current_datetime = datetime.now() - dt.timedelta(minutes=160)

# 曜日のリスト
weekdays = ['月', '火', '水', '木', '金', '土', '日']

# IDと日付を生成し、テンプレートに代入
for i in range(1, num_posts + 1):
    id = generate_id()
    current_datetime = generate_datetime(current_datetime)
  
    # 次の日付の生成のため、現在の日付を更新
      
    # IDと日付をテンプレートに代入
    date_string = current_datetime.strftime("%Y/%m/%d") + '(' + weekdays[current_datetime.weekday()] + ') ' + current_datetime.strftime("%H:%M:%S.") + str(randint(10,99))
    template = template.replace('{id}', str(id), 1)
    template = template.replace('{dateTime}', date_string, 1)
    template = template.replace('{idx}', str(i), 2)

threadkeishiki = template  # 生成したスレッド形式を変数に設定

print(threadkeishiki)

prompt = f"""
設定に基づき選ばれた{num_posts}人の(省略。自分でうまく設定してください。)
書き出しは必ず以下から始めてください。
{thread_title}
"""

sysrole = f"""(省略。自分でうまく設定してください。)'

設定:
(省略。自分でうまく設定してください。)'

出力形式:
形式は「テンプレート」の日時IDを全てそのまま使用し、[キャラクターnの投稿内容]に、(省略。自分でうまく設定してください。)'

テンプレート:
{threadkeishiki}
"""

MAX_TRIES = 3
tries = 0
thread_content = ""

while tries < MAX_TRIES:
    print(f"API呼び出しを開始しています({tries + 1}回目の試み)...")

    # API呼び出し
    response = openai.ChatCompletion.create(model="gpt-4", messages=[{"role": "system", "content": sysrole}, {"role": "user", "content": prompt}], max_tokens=4000)

    # 出力を表示
    thread_content = response["choices"][0]["message"]["content"].strip()

    if "なんJ" not in thread_content:
        print("API呼び出しが完了しました。")
        break
    else:
        tries += 1
        print(f"'なんJ'が出力に含まれているため、再試行します。")

if tries == MAX_TRIES:
    print("最大試行回数に到達しましたが、適切な出力が得られませんでした。")

# APIからのレスポンス内容内の改行を
に変換
thread_content_br = thread_content.replace('\n', '
')

# 出力を行ごとに分割
thread_lines = thread_content_br.split('
')

# 2行目の後に指定された行を挿入
insert_line = f'{selected_link}'
thread_lines.insert(2, insert_line)

# 行を再結合して更新されたスレッド内容を取得
updated_thread_content = '
'.join(thread_lines)

# GPT-3を使用してDALLEのプロンプトを作成
illustration_prompt = f"Based on the following news title and summary, suggest a short phrase that captures the theme or content of the illustration.\nTitle: {selected_title}\nSummary: {selected_summary}"
response = openai.ChatCompletion.create(
    model="gpt-3.5-turbo",
    messages=[
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": illustration_prompt}
    ],
)
dalle_prompt = response["choices"][0]["message"]["content"].strip()

# DALLEから画像を取得
response = openai.Image.create(
    prompt=dalle_prompt,
    n=1,
    size="1024x1024"
)
Image_url = response['data'][0]['url']

# 生成されたイラストのURLから画像をダウンロード
image_response = requests.get(Image_url)
image_content = image_response.content

# WordPressの設定
site_url = 'https://example.com' # 自分のサイトURLに書き換えてください
api_endpoint = '/wp-json/wp/v2/posts'
username = 'user'
password = 'pass' # 自分のに書き換えてください

# Basic Auth headerを作成
auth_string = base64.b64encode(f'{username}:{password}'.encode('utf-8')).decode('utf-8')
headers = {
    'Authorization': f'Basic {auth_string}'
}

# 画像をWordPressにアップロード
upload_endpoint = f'{site_url}/wp-json/wp/v2/media'
upload_headers = {
    'Authorization': f'Basic {auth_string}',
    'Content-Type': 'image/jpeg',
    'Content-Disposition': 'attachment; filename=image.jpg'
}
upload_response = requests.post(upload_endpoint, headers=upload_headers, data=image_content)
uploaded_image_id = upload_response.json().get("id")

# 投稿するデータを準備
data = {
    'title': thread_title,
    'content': updated_thread_content,
    'status': 'publish',
    'categories': [0],  # 自分で category IDを確認して書き換えてください
    'featured_media': uploaded_image_id
}

# POSTリクエストを送信して新しい投稿を作成
response = requests.post(f'{site_url}{api_endpoint}', headers=headers, json=data)
print("Posted to WordPress:", response.json())

スクリプトの主要機能解説

ライブラリのインポート

必要なライブラリをインポートします。

OpenAI APIキーの取得

環境変数からOpenAIのAPIキーを取得します。

RSSフィードの取得とパース

RSSフィードを取得し、エントリーをパースします。

エントリーのソートと出力

エントリーを公開日時でソートし、最新のエントリーを出力します。

ランダムなエントリーの選択

最新のエントリーからランダムに1つを選択します。

タイトルと概要の調整

OpenAI APIを使用して、選択したエントリーのタイトルと概要を調整します。

スレッドタイトルの作成

調整されたタイトルと概要を基に、スレッドタイトルを作成します。

スレッド形式の生成

指定された書き込み数に基づいて、スレッド形式を生成します。

OpenAI APIの呼び出し

指定されたプロンプトを使用してOpenAI APIを呼び出し、スレッドの内容を取得します。

イラストのプロンプトの作成

ニュースのタイトルと概要を基に、イラストのテーマや内容を捉える短いフレーズを提案するプロンプトを作成します。

イラストの取得

DALLEからイラストを取得します。

WordPressへの投稿

生成されたスレッド内容とイラストを使用して、WordPressに新しい投稿を作成します。

締めの言葉

このガイドを参考に、OpenAIを活用したRSSフィードの解析とWordPressへの投稿を行うことができます。さらなるカスタマイズや機能追加を通じて、より高度なアプリケーションを構築してみてください。

コメント

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