はじめに

先ほどの「初めてのAI作成記事」を投稿した際に、ちょっとしたトラブルが発生したので、これもGeminiに相談して解決してもらいました。今回はそのトラブルの内容と解決手順も記事にして残しておきます。

具体的には、BloggerにAIで自動投稿した際に、以下のような 2つの奇妙な現象 に遭遇しました。

  1. 個別記事では画像が正常に見えるのに、トップページ(一覧)のサムネイルが「NO IMAGE」になってしまう
  2. トップページに記事が1件しか表示されず、他の過去記事が勝手に2ページ目以降に送られてしまう

今回は、この2つのトラブルが起きた 根本的な技術的理由 と、Geminiと一緒に Google Cloud Storage(GCS)を活用して完全自動で解決した方法 をメモしておきます。


トラブル1: なぜ一覧で「NO IMAGE」になるのか?

原因:Bloggerテンプレートの画像抽出仕様

Blogger(および人気テンプレート「QooQ」など)は、記事一覧のサムネイルを表示する際、以下の仕組み(data:post.firstImageUrl)を使っています。

<!-- テンプレートのサムネイル抽出コード例 -->
<div class='article-thumbnail'>
  <b:if cond='data:post.firstImageUrl'>
    <a expr:href='data:post.url'><img expr:src='data:post.firstImageUrl'/></a>
  <b:else/>
    <!-- 画像URLが見つからない場合はNO IMAGEを表示 -->
    <img src='.../noimage.png'/>
  </b:if>
</div>

Bloggerのシステムは、記事のHTML内をスキャンして 一番最初にある <img> タグの src 属性(Web URL) を自動抽出します。

しかし、プログラム等で画像を Base64(src="data:image/webp;base64,..." で直接HTMLに埋め込んでしまうと、Bloggerは「有効なWeb URLではない」と判定して無視してしまいます。
その結果、個別記事では画像が表示されるのに、一覧では画像なし(NO IMAGE)になってしまうのです。

📌 IMPORTANT > **サムネイルを認識させる条件** > 記事の先頭にある `` の `src` 属性に、必ず **`https://` から始まる正規のWeb画像URL** を指定する必要があります。

トラブル2: なぜ1件だけで他の記事が次のページに送られたのか?

原因:Bloggerの「自動改ページ(Auto Pagination)」仕様

Bloggerには、設定画面で「メインページに表示する投稿数:10件」と指定していても、1ページの総データ容量(HTMLサイズ)が一定(約1MB)を超えると、強制的に改ページして残りを次のページへ送る という仕様があります。

Base64で画像を埋め込むと、画像データ全体が膨大な文字列となってHTMLサイズが数メガバイトに跳ね上がります。
そのため、たった1記事だけで容量上限に達してしまい、他の記事がすべて2ページ目に押し出されてしまった のです。


解決策:GCS(無料枠)への自動アップロードで完全解決!

この2つの問題を同時に解決する最もスマートな方法が、Google Cloud Storage(GCS) の活用です。

[画像生成 / ローカル画像]
       ↓ (Pythonで自動アップロード)
[GCS 無料バケット (tanog-blogger-images)]
       ↓ (公開URL: https://storage.googleapis.com/... を取得)
[Blogger 記事HTML の先頭に挿入]

メリット

  1. 正規の HTTPS 画像URLになる: Bloggerがサムネイル画像(firstImageUrl)として自動認識し、一覧に綺麗なサムネイルが表示される。
  2. HTMLサイズが超軽量になる: 記事本文には短いURLが入るだけなので、Bloggerの自動改ページ問題が解消され、一覧に設定通りの件数が正しく並ぶ。
  3. 完全無料(0円)で運用可能: GCS の Always Free 枠(米国マルチリージョンで月 5GB / 転送 100GB まで無料)により、ブログ画像であれば永久に無料で運用可能。

具体的な自動化の実装例(Python)

MCPサーバーや投稿スクリプトに、以下のようなGCSアップロード処理を組み込むだけで自動化できます。

import datetime, mimetypes
from googleapiclient.discovery import build
from googleapiclient.http import MediaFileUpload

BUCKET_NAME = "tanog-blogger-images"

def upload_to_gcs(local_image_path: str) -> str:
    # GCS API クライアントでバケットへアップロード
    service = get_storage_service()
    now = datetime.datetime.now()
    remote_name = f"articles/{now.strftime('%Y/%m')}/{os.path.basename(local_image_path)}"

    mime_type, _ = mimetypes.guess_type(local_image_path)
    media = MediaFileUpload(local_image_path, mimetype=mime_type or 'image/webp')

    service.objects().insert(
        bucket=BUCKET_NAME,
        name=remote_name,
        media_body=media
    ).execute()

    # 公開URLを返す
    return f"https://storage.googleapis.com/{BUCKET_NAME}/{remote_name}"

あとは記事の先頭に以下のようにリンク付き画像タグを挿入するだけです:

<div class="separator" style="clear: both; text-align: center; margin-bottom: 24px;">
  <a href="https://storage.googleapis.com/..." style="display: block; padding: 1em 0; text-align: center;">
    <img alt="タイトル" border="0" src="https://storage.googleapis.com/..." />
  </a>
</div>
<!--more-->

まとめ

  • サムネイルが出ない原因: Base64埋め込みはBloggerが認識できない(https:// の正規URLが必要)。
  • 1件で改ページされる原因: 記事のHTML容量オーバーによるBloggerの自動改ページ機能。
  • 解決策: GCS(常時無料枠)に画像を自動アップロードしてURLを挿入し、<!--more--> を適切に配置する。

BloggerでAPIや外部ツールを使って記事を投稿・自動化する際は、ぜひ参考にしてみてください!