カテゴリー: SNS自動化

  • Instagram自動化で制裁の引き金になったのは操作数ではなくページを開いた回数だった

    Instagram自動化で制裁の引き金になったのは操作数ではなくページを開いた回数だった

    Instagramの自動フォローを新規アカウントで試したところ、フォローを1件も実行していない段階でパスワード変更を要求されました。同じ日に同じアカウント・同じサーバーで方式だけを変えたところ、48件連続でフォローしても警告は出ませんでした。この記事では、その2回の実測で何が変わったのかを書きます。

    1回目:フォロー0件でパスワード変更を要求された

    最初に組んだのは、ハッシュタグを巡回して投稿を開き、そこから対象を拾う方式でした。ハッシュタグを12個回り、投稿を120本以上開いたところで止まりました。

    この時点でのフォロー実行数は0件です。まだ1件もフォローボタンを押していません。それでもパスワード変更を要求されました。

    自動化の制裁というと「フォローしすぎた」という話になりがちですが、この回に関してはフォロー数が原因ではありえません。押していないからです。

    2回目:フォロワー一覧を1回開くだけに変えた

    同じ日、同じアカウント、同じサーバーのまま、対象の集め方だけを変えました。投稿を1本ずつ開くのをやめ、フォロワー一覧を1回開いて、そこから対象を取る方式です。

    結果は次の通りです。

    1回目: ハッシュタグ12個 / 投稿120本以上を開く / フォロー0件 → パスワード変更要求
    2回目: フォロワー一覧を1回開く / フォロー48件連続 → 警告なし
    間隔: どちらも30〜60秒(変更なし)
    アカウント: 同一 / サーバー: 同一 / 実行日: 同一
    

    間隔は1回目も2回目も30〜60秒で揃えてあります。アカウントもIPも同じです。変えたのは「開いたページの数」だけでした。

    変数を1つに絞れたので言えること

    この2回の比較で、次の要素は原因から外れます。

    • フォロー数 … 1回目は0件で止められている
    • IP・サーバー … 両方とも同じものを使っている
    • アカウントの新しさ … 同一アカウント。2回目も新規のまま
    • 実行間隔 … どちらも30〜60秒
    • 日付・時間帯 … 同じ日

    残るのは、短時間に何ページ開いたかという点です。120本以上の投稿ページを開いた側だけが止められ、一覧を1回開いただけの側は48件のフォローを通しました。

    ただし、これは2回の実測から言えることであって、Instagram側が実際に何をカウントしているかは分かりません。私が確認できたのは「ページを開く回数を減らしたら通った」という事実だけです。閾値が何ページなのか、どのくらいの時間幅で見ているのかは、この2回では分かっていません。

    押した数とフォロー中の数が合わない

    2回目でもう一つ分かったことがあります。フォローボタンは48件押しましたが、プロフィールの「フォロー中」は36件しか増えませんでした。

    差の12件は、非公開アカウントへのフォロー申請です。申請中の状態は、相手が承認するまでフォロー中としてカウントされません。バグでも失敗でもありません。

    これを知らないと、自動化ツールのログ(48件成功)と画面の表示(36件)が食い違って見えます。「ツールが嘘をついている」「途中でブロックされた」と誤解して、無駄に設定を疑うことになります。実行数を管理するなら、押した数と反映された数は別物として持っておく必要があります。

    設計として何を変えたか

    2回目の方式は、対象の取得元を「1ページ」に固定しています。ハッシュタグ巡回のように、対象を探す過程でページ遷移が積み上がる作りをやめたということです。

    自動化を組むとき、意識が向くのは実行する操作(フォロー、いいね)の回数と間隔です。しかし1回目で分かったのは、操作に到達する前の「探す」工程だけで止められるということでした。間隔を空けても、その間に何ページも開いていれば意味がありません。数える対象を、操作数からページを開いた回数に切り替える必要があります。

    分かっていないこと

    • 何ページで閾値に達するのか。120本以上で止まったことしか分かっていません
    • どのくらいの時間幅でカウントされているのか
    • 48件がフォローの上限なのかどうか。48件で警告が出なかっただけで、それ以上は試していません
    • この挙動が他のアカウントでも同じかどうか。試したのは1アカウントです

    まとめ

    • 新規アカウントで、フォロー0件・投稿120本以上を開いた段階でパスワード変更を要求された
    • 同じアカウント・同じサーバー・同じ日に、フォロワー一覧を1回開く方式へ変更したら、48件連続フォローで警告が出なかった
    • 間隔はどちらも30〜60秒で同一。フォロー数でもIPでもなく、短時間に開いたページ数が引き金だった
    • フォローボタンを48件押しても「フォロー中」は36件しか増えない。差分は非公開アカウントへの申請中で、承認まで数えられない仕様
    • 閾値の具体的な数値や時間幅、他アカウントでの再現性は、この2回では分かっていない
  • SNS APIのページング処理は再試行を入れないと止まる

    SNS APIのページング処理は再試行を入れないと止まる

    この記事では、SNSのAPIでフォロワー一覧のような大量データをページングで取得するときに、再試行を入れていないと処理全体が落ちるという話を書きます。実際に InvokeTimeoutError で止まった経験と、そのとき例外の中身が空でログが役に立たなかった件、そこから入れた2つの対策をまとめます。

    ページングは「1回失敗したら全部落ちる」構造になっている

    フォロワー一覧のような大量データは、一度のリクエストでは取り切れないのでページングで取得します。これ自体は当たり前の話なのですが、運用してみると問題は件数が増えたときに出てきます。

    1,000人を超えると、取得は10回以上のリクエストになります。つまり、10回以上の通信のうち途中で1回でも失敗すると、そこで例外が上がって処理全体が落ちます。1回あたりの失敗率が低くても、回数が増えれば全体としてどこかで踏むことになります。ページングを素直に while で回しただけのコードは、この構造をそのまま抱えています。

    実際に InvokeTimeoutError で止まった

    実際に止まったときの例外は InvokeTimeoutError でした。名前のとおり呼び出しがタイムアウトしたということは分かりますが、問題はそこから先です。

    そのとき私のログには例外を str(e) で記録していました。ところがこの例外は str(e) が空文字でした。結果、ログに残ったのはエラーが起きたという事実だけで、何が起きたのかが分からない状態になりました。ログを見返しても、空文字が1行あるだけです。

    # ログに残っていたもの(イメージ)
    ERROR: フォロワー取得に失敗しました: 
    

    原因が分からないまま、まず「落ちないようにする」ことと「次に落ちたときに分かるようにする」ことの両方が必要だと判断しました。

    対策1:ページング呼び出しを再試行でくるむ

    ページングのAPI呼び出しを、再試行つきの関数でくるみました。待ち時間は10秒・20秒・30秒と伸ばし、最大4回まで試します。

    waits = [10, 20, 30]  # 4回目まで試す(初回 + 3回の再試行)
    
    for i in range(4):
        try:
            return call_api(cursor)
        except Exception as e:
            if i == 3:
                raise
            log_error(e)
            sleep(waits[i])
    
    • 1回の失敗で処理全体が落ちる、という構造をここで切ります
    • 待ち時間を伸ばすのは、即座に再試行しても同じ結果になる場合を想定してのことです
    • 4回試してもだめなら、そこは素直に落とします

    なお、この待ち秒数と回数が最適かどうかは分かっていません。私の環境で止まらなくなったという以上のことは言えません。

    対策2:ログに型名とトレースバックの最後の1行を入れる

    今回いちばん効いたのはこちらです。str(e) だけを記録していると、中身が空の例外に当たった瞬間に手がかりが完全になくなります。実際にそうなりました。

    そこで、ログには必ず次の2つを入れるようにしました。

    • 例外の型名(今回でいえば InvokeTimeoutError
    • トレースバックの最後の1行
    log_error(
        "type=" + type(e).__name__ +
        " msg=" + str(e) +
        " tb=" + traceback.format_exc().strip().splitlines()[-1]
    )
    

    型名が残っていれば、メッセージが空でも「何の例外か」は分かります。トレースバックの最後の1行があれば、どこで起きたかの手がかりになります。逆に言うと、この2つを入れていなかったために、最初の障害では原因の切り分けができませんでした。

    まとめ

    • フォロワー一覧のような大量データはページングで取得するため、1,000人を超えると10回以上のリクエストになります
    • その構造上、途中で1回失敗すると処理全体が落ちます
    • 実際に InvokeTimeoutError で処理が止まりました
    • そのとき str(e) が空文字だったため、ログを見ても原因が分かりませんでした
    • 対策1:ページング呼び出しを再試行でくるむ(10秒・20秒・30秒と待って4回まで)
    • 対策2:ログに例外の型名とトレースバックの最後の1行を必ず入れる
    • str(e) だけを記録すると、中身が空の例外に当たったときに手がかりを完全に失います
  • Bluesky APIのレート制限の実際(ポイント制)

    Bluesky APIのレート制限の実際(ポイント制)

    この記事で分かること

    Bluesky APIの書き込みレート制限が「回数」ではなく「ポイント制」で管理されていること、そして実際に4アカウントを1台のVPSから運用してみて、どのくらいの操作量なら上限に当たらなかったのかをまとめます。理論上限と実運用の数字の距離感をつかむための記事です。

    Blueskyの書き込み制限はポイントで数える

    Blueskyの書き込み系操作には、1時間あたり5,000ポイントという上限があります。ここが最初に理解しておくべき点で、「1時間に何回まで」という単純な回数制限ではありません。操作の種類ごとに消費するポイントが違います。

    レコード作成(投稿・フォロー・いいね)  3ポイント
    レコード削除(アンフォローなど)      1ポイント
    
    1時間の上限:5,000ポイント
    

    つまり、同じ「1回のAPI呼び出し」でも、フォローとアンフォローではコストが3倍違うということです。

    理論上限を計算してみる

    5,000ポイントを操作種別ごとに割り切ると、1時間の理論上限はこうなります。

    • フォロー(3ポイント)だけを回した場合:約1,666回
    • アンフォロー(1ポイント)だけを回した場合:5,000回

    いいねも投稿もレコード作成なので3ポイント、つまりフォローと同じ枠を食い合います。「いいねは軽い操作だから多めに回せる」という発想は、Blueskyのポイント制では成り立ちません。ここを勘違いすると設計を間違えます。

    実際に運用している量

    私が現在回している量は、1アカウントあたり1日でこの程度です。

    いいね      700 /日
    フォロー    400 /日
    アンフォロー 600 /日
    

    これをポイントに換算すると、いいねとフォローが作成系なので (700 + 400) × 3、アンフォローが 600 × 1 です。1日単位の合計としては、1時間の上限5,000ポイントを大きく上回る量になります。したがって、この運用は「1時間に詰め込む」やり方では絶対に成立しません。24時間に分散させることが前提の数字です。

    この状態で4アカウントを1台のVPSから動かしていますが、上限に当たったことはありません。レート制限はアカウント単位で効いているため、1台のVPSに何アカウント載せているかは(少なくともこの規模では)問題になっていません。

    RateLimitExceeded が出たのは設計ミスの時期だけ

    正直に書くと、`RateLimitExceeded` を踏んだことはあります。ただしそれは設計を誤っていた時期に限られます。処理を時間軸に分散させる仕組みを入れてからは、エラーは0件です。

    教訓としては単純で、1日の総量が上限を超えているかどうかではなく、ある1時間に何ポイント集まっているかだけが問題だということです。1日700いいねという数字自体は何の危険信号でもなく、それを起動時に一気に流すか、時間をかけて散らすかで結果が変わります。

    設計するときに意識していること

    • いいね・フォロー・投稿はすべて3ポイントの同じ枠なので、合算して見積もる
    • アンフォローは1ポイントなので、整理系の処理は比較的余裕がある(それでも同じ5,000ポイントを共有している)
    • 1日の総量から逆算して、1時間あたりの消費ポイントが5,000に届かないよう時間を分散させる
    • 複数アカウントでも、それぞれのアカウントのポイント消費だけを見る

    分かっていないこと

    私が確認できたのは、上に書いた運用量では上限に当たらなかった、という事実だけです。この量よりどこまで増やせるのか、上限に近づいたときにどういう挙動になるのかは、意図的に試していないので分かりません。また、ここで挙げたポイント値以外の操作のコストについても、私は検証していません。「この数字なら安全」と一般化できる根拠は持っていない、というのが正確な状態です。

    まとめ

    • Blueskyの書き込み制限は1時間あたり5,000ポイントのポイント制
    • レコード作成(投稿・フォロー・いいね)は3ポイント、削除(アンフォロー)は1ポイント
    • 理論上限はフォローで約1,666回/時、アンフォローで5,000回/時
    • 実運用は1アカウント1日あたり700いいね・400フォロー・600アンフォローで、4アカウントを1台のVPSから回して上限に当たっていない
    • 1日の総量ではなく「1時間に何ポイント集まるか」が本質。時間分散を入れてから RateLimitExceeded は0件
    • これ以上の量でどうなるかは検証していないため分からない