以前XがまだTwitterだった頃、画像付きの記事を自動でtweetするアプリを作成していた。
記事フォルダに投稿したい記事を格納し、画像フォルダには記事と一緒に投稿したい画像を最大4つ格納しておくと、事前に設定しておいた間隔で記事を投稿していくものだった。
TwitterがXとなりAPIも色々と変更されたため、Xでの画像付きの自動投稿はやめていた。
(さらにXのAPI無料枠が無くなり有料になったこともあり、復活させることも諦めていた)
そんな中で、最近妻が良くThreadsを利用しているので、Threadsに自動投稿してみようかと思いAIに相談してみた。
すると簡単に作れるという回答だった。
アプリを作る時に昔はchat版Geminiに相談していたが、最近は基本Antigravityに相談していた。chat型でも作ってもらえるのだが、一旦ソースをコピーしてローカルで作業して動かす作業もそうだが、トラブルがあった場合の修正作業が結構大変だったからだ。
Antigravityならローカル環境にアクセスが出来るのでこちらの作業が非常に簡単になるのが大きかった。
しかし、ある意味あっという間にトークンを使ってしまうのが問題だった。特に最近は定常的に実施する作業も増えてきており、なかなか非定例的な作業に使う枠が賄えない感じになっているからだ。
chat版Gemini、Antigravityの他にもう一つ無料枠で開発を頼めるGeminiがある。以前も紹介したAI Studioだ。(Xのツリー投稿が面倒すぎる問題を解決!AI StudioとPython(標準機能のみ)で作った半自動投稿アシスタント【コード全文公開】)今回はそれを使うことにした。
以下がThreadsに画像付きで記事を自動投稿するアプリの開発記だ。(まずはAI Studioと仕様を詰めていくところからスタートした。)
AI Studioとアプリ仕様の策定
アプリ作成の前に、まずは実現可能かどうかをAI Studioに確認してみた。
事前にSNSpost用の記事を書いておき、画像を添付してThreadsやInstagramへ一定間隔で自動投稿するアプリは作成可能か?今すぐ作るのではなく可否を答えて欲しい。
結論から申し上げますと、公式API(Instagram Graph API / Threads API)を利用することで作成可能です。ただし、以下の前提条件があります。
- アカウント要件:Instagramはプロアカウント(ビジネス/クリエイター)である必要がある
- 開発者登録:Meta for Developersでの登録や権限審査が必要
- 画像の配置場所:API経由で投稿する場合、ローカルの画像を直接送信するのではなく、一度インターネット上に公開した画像のURLをAPIに渡す仕組みが必要
- 投稿制限:短時間での連続投稿を避け、レートリミットを遵守したスケジューラーが必要
これらを踏まえ、デスクトップアプリとしての具体的な使い勝手や仕様を相談しながら詰めていった。私から伝えた主な要望は以下の通りだ。
- アプリ形態:基本はPythonスクリプト+設定項目を管理できるシンプルなGUI(デスクトップアプリ)
- スケジュール:キュー(フォルダ内の古い順)処理とし、投稿禁止時間帯も設定可能にする
- 対象SNS:InstagramとThreadsは将来的に別アプリとして分離できるようにする
- 動作環境:PC起動中のみ動作すればOK(常駐サーバーは不要)
- マルチアカウント:1台のPCで複数アカウント(プロファイル)を同時に立ち上げられるようにする
投稿用の画像はインターネット上に置かなければならない
ここで技術的な最重要ポイントとなったのが「画像ファイルの扱い」だ。
Twitter APIなどのようにPC内の画像を直接POST送信できるものと思っていたのだが、Metaの公式APIは仕様上、「インターネット上に公開された画像のURL」をMeta側に伝え、Metaがそれを取りに来る仕組みになっているらしい。
AIからは「Cloudinaryなどの無料クラウドストレージに一時アップロードする案」や「ngrok等のトンネリングツールを使う案」を提案されたが、ふと思った。
私はすでにレンタルサーバーを契約しており、独自ドメインも持っている。これを使えないだろうか?
画像について一点確認したい。レンタルサーバーのドメイン配下にフォルダを用意し、アプリからFTPでアップロードしてそのURLをMetaに引き渡すことは可能だろうか?
結論から申し上げますと、完全に可能です。運用の手軽さやシステムの安定性を考えると、むしろ「レンタルサーバーへのFTP(またはSFTP)アップロード」が圧倒的におすすめです。
- 実装がシンプルで高速:Python標準の
ftplibだけで追加ライブラリなしに数行で実装できる - 容量圧迫なし:Meta側が画像を取り込むのは投稿リクエスト直後の数分間だけ。投稿成功後にアプリ側からサーバー上の画像を自動削除してしまえば容量を圧迫しない
- 外部制限なし:無料クラウドサービスのような転送量上限や規約変更のリスクがない
ということで、画像の外部URL化は「自前のレンタルサーバーへFTP経由で一時アップロードし、投稿完了後に自動削除する」方式に決定した。
完成した要件定義書(外部仕様)
ここまでのやり取りで方針が完全に固まったため、次の開発フェーズ(実装用チャット)へスムーズに引き継げるよう、AI Studioにコピペ用の「要件定義書」として取りまとめてもらった。
この仕様書を新しいチャットの冒頭にそのまま投入すれば、前提条件の食い違いなくコード作成に入ることができる。同様のツールを作りたい方向けに、まとまった仕様書をそのまま掲載しておく。
# 【要件定義書】Instagram / Threads 自動投稿デスクトップアプリ
事前に作成されたテキストファイルと画像群を読み込み、指定の間隔でInstagramまたはThreadsへカルーセル(複数画像)投稿を行うPC常駐型デスクトップアプリの開発。
---
## 1. システム全体構成
* **実行環境**: Windows / Mac ローカルPC(アプリ起動中のみ動作)
* **開発言語**: Python 3.10+
* **GUIライブラリ**: CustomTkinter または Tkinter(設定画面および実行ログ表示)
* **対象SNS**: Instagram(Graph API)および Threads(Threads API)
* 共通コアを持ち、ビルドまたは設定切り替えで両SNSに対応、あるいは独立した実行ファイルとしてビルド。
---
## 2. 入力ファイル仕様
### (1) 監視フォルダ構造
各アカウント(プロファイル)ごとに以下のフォルダをローカルに用意する。
* `ready/` : 投稿待ちテキストファイルを格納するフォルダ(アプリが監視)
* `done/` : 投稿成功後のファイルを移動するフォルダ
* `error/` : 投稿失敗時のファイルを移動するフォルダ
* `images/` : 投稿用ローカル画像を保存しておくフォルダ
### (2) テキストファイル形式(.txt)
* **ファイル名**: 任意(例: `202611081138記事タイトル.txt`)
* **処理順**: ファイルの作成日時(または更新日時)が古い順にキュー処理
* **内部構成**:
* **1行目**: 投稿する画像ファイル名をカンマ区切りで記述(例: `img1.jpg,img2.jpg,img3.jpg`)
* **2行目**: エラーメッセージ書き込み用(通常時は空行)
* **3行目以降**: 投稿本文(テキスト、改行、ハッシュタグ、URL等)
---
## 3. 画像ホスティング仕様(FTP経由の外部URL化)
Meta社APIが画像の外部公開URLを必須とするため、自前のレンタルサーバーを経由する。
1. **アップロード**:
* `images/` から該当画像を読み込み、レンタルサーバーの特定フォルダ(例: `public_html/sns_temp/`)にFTP/SFTPでアップロード。
* **衝突防止**: 複数起動や同名画像による上書きを防ぐため、サーバー側ファイル名を一意化(例: `{profile}_{timestamp}_{original_filename}`)。
2. **URL発行**:
* アップロード完了後、外部アクセス可能なHTTPSのURL文字列を生成。
3. **自動クリーンアップ**:
* Meta APIへ投稿が成功した直後、サーバー上の該当画像ファイルをFTP経由で自動削除。
---
## 4. 投稿・スケジューリング仕様
1. **キュー実行**:
* 設定された「投稿間隔(例: 60分)」ごとに `ready/` フォルダの最古ファイルを1件処理。
2. **投稿禁止時間帯**:
* 設定された時間帯(例: 23:00 〜 07:00)は処理を一時停止(スリープ)する。
3. **成否のハンドリング**:
* **成功時**: ファイル名の先頭に `[DONE_YYYYMMDD_HHMM]_` を付与し、`done/` フォルダへ移動。
* **失敗時**: テキストファイルの2行目にエラー内容を追記し、`error/` フォルダへ移動。処理キューは停止せず次回へ進む。
---
## 5. 複数同時起動・プロファイル機能
1台のPCで複数のInstagram/Threadsアカウントを同時に自動運用できる設計とする。
* **プロファイル管理**:
* アプリ起動時に「プロファイル名」を選択、または起動引数(`--profile Account_1`)で指定。
* プロファイルごとに固有の `config_{profile}.json` を保持。
* **分離される設定項目**:
* 認証情報(アクセストークン、アカウントID)
* フォルダパス(`ready`, `done`, `error`, `images`)
* 投稿間隔・禁止時間帯
---
## 6. GUI(設定画面)の要件
GUI上で以下の設定を変更・保存(JSON出力)でき、ワンクリックで「監視・自動投稿」を開始/停止できること。
* **SNS種別選択**: Instagram / Threads
* **API認証設定**: アクセストークン、各種ID
* **FTP設定**: ホスト名、ポート、ユーザー名、パスワード、リモートパス、公開ベースURL
* **パス設定**: 各種フォルダパス(参照ダイアログで指定可能)
* **スケジュール設定**: 投稿間隔(分指定)、投稿禁止時間帯
* **ログ画面**: 直近の処理状況、次回投稿カウントダウン、エラーログの常時表示
---
## 7. API別仕様差分
### A. Instagram Graph API (カルーセル投稿)
1. 画像ごとにコンテナ作成: `POST /{ig-user-id}/media` (`image_url`, `is_carousel_item=true`)
2. カルーセル親コンテナ作成: `POST /{ig-user-id}/media` (`media_type=CAROUSEL`, `caption`, `children=[item_id1, item_id2...]`)
3. 公開: `POST /{ig-user-id}/media_publish` (`creation_id`)
### B. Threads API (カルーセル投稿)
1. 画像ごとにコンテナ作成: `POST /{threads-user-id}/threads` (`media_type=IMAGE`, `image_url`, `is_carousel_item=true`)
2. カルーセル親コンテナ作成: `POST /{threads-user-id}/threads` (`media_type=CAROUSEL`, `text`, `children=[item_id1, item_id2...]`)
3. 公開: `POST /{threads-user-id}/threads_publish` (`creation_id`)
こうしてAI Studioとの対話を通じて、要件定義書をまとめてみた。
後編では、この仕様書をもとに新しいチャットでAI StudioにPythonコードを出力させ、デスクトップGUIの構築から実際のテスト投稿までの実装プロセスをお届けする。


