21
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

こんにちは。
リーデックス小川です。

リーデックスは、渋谷にあるシステム開発の会社です。プリザンターの3社目の公式パートナーとして8年以上プリザンターに携わってきました。最近はQiitaでのプリザンターの話題が増えてきて、ユーザーが右肩上がりに増えていることがとてもうれしく思っています。

こちらの記事は、前編です。読み終わりましたら、「PleasanterとChatGPTとWordPressでWeb記事を半自動生成(後編)」もぜひご覧ください。

昨年度の記事

毎年、プリザンターのアドベントカレンダーに参加していますが、昨年の「オープンソースのRAG「Dify」にプリザンターのデータを連携する(前半)」を書きました。

image.png

昨年度に引き続き、生成AIを組み合わせた「PleasanterとChatGPT、WordpressでWeb記事を半自動生成する」というアプリを実装してみました。

なお、このブログは2025年09月26日(金)に開催された「ユーザーミートアップ 10」で発表した内容を元に、再編集した内容です。

システムを構築しようとしたきっかけ

image.png
生成AIの有効活用を考えていた時に「特定分野のポータルサイトを作りたいが、すべてのコンテンツを作るのは手間がかかる。1コンテンツとして、指定したWebサイトを紹介する記事を生成AIを使って動的に生成できないか?」というのがきっかけでした。
プリザンターにデータを格納し、それを生成AIに処理をさせてアウトプットする、という同じような流れは、ほかにも応用が効くと思います。

システム仕様

システムの仕様は下記を想定して開発しています。

  • 指定したURLの内容を要約し、イメージ画像を生成して、WordPressに記事とアイキャッチを投稿する
  • 対象となるURLは、公式APIやRSSを利用してプリザンターに登録する
  • PHPのバッチプログラムで、生成対象となるURLをプリザンターのAPIから取得し、WordPress登録まで一気に実行する
  • 指定したWebサイトのクロールは、安全面を考慮し外部サービスのPhantomJSCloudを使用
  • 記事要約、画像生成はChatGPTのAPIを使用
  • WordPressは下書きで保存し、目視確認後に公開する運用を想定

少し前に全体構成を検討していたので、今だと画像生成はNanoBananaで生成するのもよさそうですね。また、Webサイトのクロールについては一日500ページまで無料の「PhantomJs Cloud」を使用しています。

image.png

システムの構成

image.png

システム構成ですが、大きく役割を分けるとURLを保存している「プリザンター」、Webサイトの取得、本文や画像を生成(記事・画像生成+WP連携プログラム)し、WordPressに連携する「PHP」、フロンドエンドの「WordPress」という組み合わせです。

この構成は少し冗長で、URLを保存する場所はプリザンターではなく、WordPressでもよいです(実際そのような実装も実施しています)。ただ、通常の業務を踏まえると、プリザンターに業務データを生成AIで処理、アウトプットの構造で実装しておくことで応用が効くため、あえてこの構成としました。

また、フロントエンドをWordPressとしたのは、ほかにもコンテンツを生成すること、豊富なWebサイト向けプラグインがあること(、勉強したかったこと)のためですが、Qiitaへの連携やフルスクラッチで開発してもよさそうです。今回は、できるだけフロントエンドに時間をかけない、ということもあったため、WordPressとしました。

プリザンターへのデータ登録について

URLを取得するプログラムですが、APIやRSS、メールでURLを保存しています。URL登録後に、PHPプログラム部分のAでデータを取得した際には、フラグで管理しています。
image.png

今回の仕様だと、プリザンターはヘッドレスCMSのような役割となります。実際にプリザンターをヘッドレスCMSとして利用している事例もあるようです。

今回はURLを登録するだけなので、PostgreSQLなどのデータベースで作ってもそこまで時間はかかりませんが、API、テーブル、CSVでのインポート、エクスポート、通知機能などが必要な機能がノーコードで一通りそろっているプリザンターをデータベースの代わりとして使うこともありです。

URLを登録するPHPのプログラムは下記のようになります。

//$URLsに登録するURLが配列で設定されている
$endpoint = CONST_URLS_UPSERT_ENDPOINT;
$ch = curl_init($endpoint);
$ch = set_url_setopt($ch);
for($i=0;$i<count($URLs);$i++){
    $data = array(
        "ApiVersion" => 1.1,
        "ApiKey" => CONST_API_KEY,
        "Keys"=>["ClassC"],
        "ClassHash" => [
            "ClassC"=> $URLs[$i],
        ],
    );
    
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
    $result = curl_exec($ch);
    if ($result === false) {
        $error = curl_error($ch);
        echo "cURL error: " . $error . PHP_EOL;
        continue;
    }
    $result = json_decode($result);
}
curl_close($ch);

PHPプログラム部分について

記事・画像生成+WP連携プログラム(以後PHPプログラム)は大きく3つに分かれています。

  • A.Webサイトのクローリング+スクレーピング
  • B.ChatGPTでのコンテンツ生成
  • C.WordPressへの登録

A.Webサイトのクローリング+スクレーピング

A部分では、「PhantomJs Cloud」によるクローリング→「Readability」よる本文抽出→「HTMLPurifier」によるタグ削除、と処理を実行します。

「PhantomJs Cloud」によるクローリング

まずは、「PhantomJs Cloud」を使用して、指定したURLよりデータを取得します。

// APIエンドポイント
$apiKey = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";  // ここに取得したAPIキーを入力
$url = "https://phantomjscloud.com/api/browser/v2/$apiKey/";

// HTTPコンテキストオプションを設定
$options = [
    'http' => [
        'header'  => "Content-type: application/json\r\n",
        'method'  => 'POST',
        'content' => $requestPayload
    ]
];

$context = stream_context_create($options);

// PhantomJs Cloud APIへのリクエストを送信
OgUtil::console_log("Start PhantomJs Cloud");
$html = file_get_contents($url, false, $context);
OgUtil::console_log("End PhantomJs Cloud");

「Readability」よる本文抽出

取得したデータを元に「Readability」で必要な本文のみを抽出します。
「Readability」は、Webページから主要な本文だけを高精度に抽出するためのライブラリです。不要な広告、ナビゲーション、サイドバーなどを自動で取り除き、読みやすいデータとして取得できます。もともとMozillaが開発したアルゴリズムを基にしており、スクレイピングやRSS生成、コンテンツ要約の前処理として役立ちます。複雑なHTMLでも安定して本文を抽出でき、PHPプロジェクトに簡単に組み込める点が大きな利点です。

//-------------------------------------------------------------------------------------
// Readabilityの設定
//-------------------------------------------------------------------------------------
$config = new Configuration();
$readability = new Readability($config);

// HTMLを解析
$readability->parse($html);

// 本文を取得
$content = $readability->getContent();

「HTMLPurifier」によるタグ削除

Aの最後として「HTMLPurifier」で、概要を作成する際に不要なとなるタグを削除しています。
HTML Purifierは、ユーザー入力や外部サイトから取得したHTMLを安全に整形するための強力なPHPライブラリです。HTMLを安全に整形するだけでなく「必要なHTMLだけを正確に残せる」点が大きな特徴です。ホワイトリスト方式で許可したタグのみを維持し、それ以外を自動的に除去するため、要約処理やテキスト抽出の前段として“重みづけに不要なタグを排除したクリーンなデータ”を生成できます。XSS対策としての信頼性はもちろん、AI 要約や自然言語処理の前処理にも非常に相性が良いライブラリです。

//-------------------------------------------------------------------------------------
// HTML Purifierの設定
//-------------------------------------------------------------------------------------
$purifierConfig = HTMLPurifier_Config::createDefault();

// 不要な属性を除去する設定
$purifierConfig->set('HTML.AllowedAttributes', []);
$purifierConfig->set('CSS.AllowedProperties', []);
$purifierConfig->set('HTML.ForbiddenAttributes', ['style', 'data-*']);

// 不要なタグを除去する設定(必要に応じて調整)
$purifierConfig->set('HTML.AllowedElements', ['p', 'a', 'ul', 'ol', 'li', 'strong', 'em', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6','code','img']);

// HTML Purifierのインスタンスを作成
$purifier = new HTMLPurifier($purifierConfig);

// クリーンなHTMLを取得
$cleanHtml = trim($purifier->purify($content));

この記事では、ここまでです。
続きは「PleasanterとChatGPTとWordPressでWeb記事を半自動生成(後編)」をご覧ください。

21
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
21
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?