開発者ガイド

PythonでSNS投稿を自動化する方法

スタートアップのコンテンツパイプラインを構築する場合でも、クライアントへの投稿を自動化する場合でも、SaaSプロダクトにSNS配信機能を組み込む場合でも、Pythonなら簡単に実現できます。このチュートリアルでは、最初のアップロードから本番環境で使える自動化スクリプトまで、すべてを解説します。

なぜSNS自動化にPythonなのか

Pythonは自動化の定番言語です。読みやすく、エコシステムが豊富で、スケジュール実行するスクリプトに最適です。SNSへのプログラム的な投稿に関しては、Upload-PostのようなAPIを使う代わりに、各プラットフォームのOAuth連携を自分で構築するという選択肢もあります。しかし、それはTikTokのContent Posting API、InstagramのGraph API、YouTubeのData APIなどを個別に扱うことを意味します。それぞれ独自の認証フロー、レート制限、癖があります。

ソーシャルメディア投稿APIなら、1回のAPIコールで10のプラットフォームすべてに投稿できます。Python SDKを使えばさらに簡単です。

環境のセットアップ

1. SDKをインストール

pip install upload-post

2. APIキーを取得

app.upload-post.comで無料アカウントを作成し、APIキーダッシュボードでキーを生成します。環境変数として保存してください:

export UPLOAD_POST_API_KEY="your-api-key-here"

3. SNSアカウントを接続

Upload-Postのダッシュボードでプロフィール(例: 「mybrand」)を作成し、TikTokInstagramYouTubeなど投稿したいアカウントを接続します。このプロフィール名をコード内で参照します。

最初のアップロード: 動画を投稿する

import os
from upload_post import UploadPostClient

client = UploadPostClient(
    api_key=os.environ["UPLOAD_POST_API_KEY"]
)

response = client.upload_video(
    video_path="my-video.mp4",
    title="私たちの新製品の実演",
    user="mybrand",
    platforms=["tiktok", "instagram", "youtube"]
)

if response["success"]:
    for platform, result in response["results"].items():
        if result["success"]:
            print(f"{platform}: {result['url']}")
        else:
            print(f"{platform}: upload failed")
else:
    print("Upload failed:", response)

これで動作するスクリプトの完成です。実行すれば、動画が3つのプラットフォームに公開されます。さらに機能を追加していきましょう。

写真とカルーセルの投稿

response = client.upload_photos(
    photos=["slide-1.jpg", "slide-2.jpg", "slide-3.jpg"],
    title="サマーコレクションのルックブック",
    description="すべての作品はポルトガル製。バイオのリンクから購入。",
    user="mybrand",
    platforms=["instagram", "tiktok", "linkedin"]
)

print(response)

Instagramではカルーセル投稿に、TikTokではスライドショーに、LinkedInでは複数画像投稿になります。各プラットフォームに最適な形式で配信されます。

テキストコンテンツの投稿

テキストのみの投稿(Twitterスレッド、LinkedIn投稿、Reddit投稿など):

response = client.upload_text(
    title="私たちはAPIに大規模なアップデートを出荷しました。変更点は以下の通りです...",
    user="mybrand",
    platforms=["x", "linkedin", "threads", "bluesky"]
)

print(response)

テキストがプラットフォームの文字数制限を超える場合、APIがスマートに処理します。Xでは280文字を超えると自動的にスレッドになります。スレッドでは500文字で分割、Blueskyでは300文字で分割されます。

プラットフォーム固有のパラメータを使う

titleパラメータはすべてのプラットフォームのデフォルトキャプションになりますが、プラットフォームごとに異なるコピーを設定したいことも多いでしょう。プラットフォームごとのカスタマイズ方法は以下の通りです:

import requests
import os

API_KEY = os.environ["UPLOAD_POST_API_KEY"]

with open("product-demo.mp4", "rb") as video:
    response = requests.post(
        "https://api.upload-post.com/api/upload",
        headers={"認可": f"APIキー {API_KEY}"},
        files={"video": video},
        data={
            "user": "mybrand",
            "title": "Check this out",
            # Platform specific titles
            "tiktok_title": "視点: あなたの製品は自分で売れる #ecommerce #dropshipping",
            "instagram_title": "新しいリリース。早期アクセスのためのリンクはプロフィールにあります。",
            "youtube_title": "製品デモ | 完全レビュー",
            "youtube_description": "このビデオでは、どのように機能するかを正確に示します...",
            "linkedin_title": "コミュニティと最新の製品ローンチを共有できることに興奮しています。",
            # Platform specific settings
            "platform[]": ["tiktok", "instagram", "youtube", "linkedin"],
            "privacy_level": "PUBLIC_TO_EVERYONE",
            "media_type": "REELS",
            "tags[]": ["product", "demo", "review"],
            "privacyStatus": "public",
        }
    )

print(response.json())

この例ではSDKの代わりにrequestsライブラリを直接使用しており、すべてのAPIパラメータにアクセスできます。各プラットフォームで利用可能なすべてのオプションは完全なAPIリファレンスをご確認ください。

投稿を予約する

from datetime import datetime, timedelta

# Schedule for tomorrow at 9 AM
tomorrow_9am = (datetime.now() + timedelta(days=1)).replace(
    hour=9, minute=0, second=0, microsecond=0
)

response = client.upload_video(
    video_path="tomorrows-content.mp4",
    title="おはようございます!フィードのための新鮮なコンテンツ",
    user="mybrand",
    platforms=["tiktok", "instagram"],
    scheduled_date=tomorrow_9am.isoformat(),
    timezone="アメリカ/ニューヨーク"
)

print(f"スケジュールされました!ジョブID: {response['job_id']}")
print(f"公開予定: {response['scheduled_date']}")

最大365日先まで予約できます。スケジューリングとキューシステムの詳細はスケジューリングガイドをご覧ください。

本格的な自動化: フォルダ監視スクリプト

フォルダ内の新しい動画ファイルを監視して自動的にアップロードする実用的なスクリプトです。共有フォルダでクライアントのコンテンツを受け取る代理店に最適です:

import os
import time
import json
from upload_post import UploadPostClient

client = UploadPostClient(
    api_key=os.environ["UPLOAD_POST_API_KEY"]
)

WATCH_FOLDER = "/path/to/content/inbox"
PROCESSED_FILE = "/path/to/content/processed.json"
CHECK_INTERVAL = 60  # seconds

def load_processed():
    if os.path.exists(PROCESSED_FILE):
        with open(PROCESSED_FILE) as f:
            return set(json.load(f))
    return set()

def save_processed(processed):
    with open(PROCESSED_FILE, "w") as f:
        json.dump(list(processed), f)

def upload_video(filepath):
    filename = os.path.basename(filepath)
    title = filename.rsplit(".", 1)[0].replace("-", " ").replace("_", " ")

    response = client.upload_video(
        video_path=filepath,
        title=title,
        user="mybrand",
        platforms=["tiktok", "instagram", "youtube"],
        add_to_queue=True,
        async_upload=True
    )
    return response

print(f"Watching {WATCH_FOLDER} for new videos...")

processed = load_processed()

while True:
    for filename in os.listdir(WATCH_FOLDER):
        if filename in processed:
            continue
        if not filename.lower().endswith((".mp4", ".mov")):
            continue

        filepath = os.path.join(WATCH_FOLDER, filename)
        print(f"New file detected: {filename}")

        try:
            result = upload_video(filepath)
            print(f"  Queued successfully: {result.get('job_id', 'done')}")
            processed.add(filename)
            save_processed(processed)
        except Exception as e:
            print(f"  Error: {e}")

    time.sleep(CHECK_INTERVAL)

このスクリプトをバックグラウンド(またはsystemdサービスとして)で実行すると、フォルダに動画がドロップされるたびに、接続済みの全プラットフォームに自動配信されます。より堅牢な仕組みが必要な場合は、n8nMake.comのマネージドワークフローの利用を検討してください。

APIを直接使う(SDKなし)

SDKを使いたくない場合や、より低レベルな制御が必要な場合は、requestsライブラリを直接使用できます。SDKアップロードと同等のコードは以下の通りです:

import requests

API_KEY = "your-api-key-here"
API_URL = "https://api.upload-post.com/api/upload"

# Upload a video
with open("video.mp4", "rb") as f:
    response = requests.post(
        API_URL,
        headers={"認可": f"APIキー {API_KEY}"},
        files={"video": ("video.mp4", f, "video/mp4")},
        data={
            "user": "mybrand",
            "title": "Pythonリクエストで投稿されました。",
            "platform[]": ["tiktok", "instagram"],
        }
    )

print(response.status_code)
print(response.json())

APIキーの検証

大量バッチを実行する前に、キーが有効であること、プランの上限を確認しておくことをお勧めします:

response = requests.get(
    "https://api.upload-post.com/api/uploadposts/me",
    headers={"認可": f"APIキー {API_KEY}"}
)

data = response.json()
print(f"メール: {data['email']}")
print(f"プラン: {data['plan']}")

エラーハンドリングのベストプラクティス

本番スクリプトを構築する際に対処すべき一般的なシナリオ:

import requests

def upload_with_retry(video_path, title, platforms, max_retries=3):
    for attempt in range(max_retries):
        try:
            with open(video_path, "rb") as f:
                response = requests.post(
                    "https://api.upload-post.com/api/upload",
                    headers={"認可": f"APIキー {API_KEY}"},
                    files={"video": f},
                    data={
                        "user": "mybrand",
                        "title": title,
                        "platform[]": platforms,
                        "async_upload": "true",
                    },
                    timeout=120
                )

            if response.status_code == 200:
                return response.json()
            elif response.status_code == 429:
                # Rate limited, check usage
                usage = response.json().get("usage", {})
                print(f"Rate limited. Used {usage.get('count')}/{usage.get('limit')}")
                return None
            elif response.status_code == 401:
                print("Invalid API key")
                return None
            else:
                print(f"Attempt {attempt + 1} failed: {response.status_code}")

        except requests.exceptions.Timeout:
            print(f"Attempt {attempt + 1} timed out, retrying...")

    print(f"全ての{max_retries}試行が{video_path}に対して失敗しました")
    return None

アップロード履歴の確認

アップロード履歴を取得して、何が成功したかの確認やレポートダッシュボードの構築ができます:

response = requests.get(
    "https://api.upload-post.com/api/uploadposts/history?page=1&limit=20",
    headers={"認可": f"APIキー {API_KEY}"}
)

for entry in response.json()["history"]:
    status = "OK" if entry["success"] else "FAILED"
    print(f"[{status}] {entry['platform']} - {entry['post_title']} - {entry['post_url']}")

次のステップ

基本が理解できたところで、次に構築できるアイデアをいくつか紹介します:

今日からPythonで自動化を始めましょう

SDKをインストールしてAPIキーを取得すれば、5分以内に最初の動画を配信できます。無料プランで月10回のアップロードが含まれます。

pip install upload-post