ガイド
エミュレータ多重起動で複数アカウントを自動化する
MAS での Android エミュレータ多重起動: BlueStacks や LDPlayer の各インスタンスをポートで追加してグループ化し、デバイスごとにプロファイルとプロキシを持たせます。
- Windows
- Mac
- エミュレータ
- Studio
- Python SDK
このページの内容
- 始める前に
- 多重起動した Android エミュレータの各インスタンスはデバイス
- デバイスグループを作る
- 各デバイスに固有の引数を与える
- 各デバイスに固有のプロキシを与える
- すべて開始: LDPlayer や BlueStacks での多重起動の同期
- ストレージでデバイスごとの状態を保つ
- グループごとの Webhook
- BlueStacks の bot ファームのリソース上限に注意する
- グループをスケジュールする
- 完全な例
- うまくいかないとき
- Port is already in use
- 1 つのインスタンスは動くが、残りは Connecting のまま
- テンプレートが 1 つのインスタンスでしか一致しない
- すべてのインスタンスが 1 つのカウンターを共有する
1 つのマクロ、5 つのアカウント、1 回のクリック: それがエミュレータの多重起動による周回 (ファーミング) です。Macro Automation Studio (MAS) は、多重起動した Android エミュレータの各インスタンスを別々のデバイスとして扱います。デバイスグループがそのすべてで同じマクロを、デバイスごとの引数、それぞれのプロキシ、カウンターが混ざらないストレージとともに実行します。このガイドでは、BlueStacks、LDPlayer、MuMu Player、MEmu でその構成を作ります。複数のアカウントを動かすすべての方向けです。
始める前に
- MAS がインストール済みで、同時に動かしたいインスタンス数をデバイス数がカバーするプランでサインインしていること。お支払い を参照してください。
- エミュレータのマルチインスタンスマネージャーでインスタンスを作成し、それぞれで ADB を有効にしてあること。BlueStacks、LDPlayer、MuMu Player、MEmu のガイドで設定とポートの場所を示しています。
- すべてのインスタンスが、テンプレートを取り込んだものと同じ解像度と DPI を使っていること。
- マクロが Code Editor から 1 つのインスタンスで動くこと。ループガイド を参照してください。
多重起動した Android エミュレータの各インスタンスはデバイス
エミュレータのインスタンスは、それぞれ固有のローカル TCP ポートで adb を待ち受けます。MAS は起動中のプロセスをスキャンし、各エミュレータの既知の範囲内のポートを残してインスタンスを見つけます。したがって BlueStacks のウィンドウが 2 つあれば、ポート 一覧に 2 つの項目として現れます。デバイスはポートであり、グループはポートの一覧です。
| エミュレータ | MAS が受け付けるポート |
|---|---|
| BlueStacks | 5555 から 8500 |
| LDPlayer | 5555 から 5599 の奇数ポート |
| MuMu Player | 5555 から 5599 の奇数ポート、7555、16384 から 16576、26624 から 27264 |
| MEmu | 21503 と、それより上で 30000 未満の末尾が 3 のすべてのポート |
追加する間はすべてのインスタンスを開いたままにしてください。停止中のインスタンスには見つけるべきポートがありません。完全な検出規則は デバイス ページにあります。
デバイスグループを作る
- デバイスグループ を開き、新しいグループを作成 をクリックします。
- 名前 を入力し、種類は ローカル のままにして、グループを作成 をクリックします。
- グループを開き、デバイスを追加 をクリックします。
- どのアカウントかが分かる デバイス名 を入力します (例:
farm-alt-2)。 - ポート でインスタンスのポートを選びます。見当たらなければ 更新 をクリックするか、カスタムポート を選んで入力します。
- デバイスを追加 をクリックし、すべてのインスタンスについて繰り返します。
- 各デバイスカードで、マクロ セレクターでマクロを選びます。
ポートは 1 台のデバイスにしか属せません。2 度追加すると「Port is already in use」で失敗します。デバイスグループ を参照してください。
各デバイスに固有の引数を与える
ほとんどの bot には、アカウントごとに異なる値が 1 つ必要です: 名前、目標、周回数。渡す方法は 2 つあります。
設定プロファイル (コード変更なし)。 マクロに UI Builder の引数フォームがある場合、各デバイスカードに 引数を編集 があります。ダイアログには プロファイル バーがあります: 値を入力し、現在の値を新しいプロファイルとして保存 を選び、名前を付けて プロファイルを作成 をクリックします。デバイスは 1 つのプロファイルに従い、プロファイルを編集すると、それに従うすべてのデバイスが次回の実行で更新されます。「Default」は常に存在し、削除できません。設定プロファイル と UI Builder を参照してください。
コード内のポート。 スクリプトは自分がどのインスタンスにいるかを尋ね、自分の設定を選べます。フォームは不要で、最後の例がこの方法です。
import mas
port = mas.get_current_device_port() # 5555, 5557, 5559 ...値が頻繁に変わるときや他の人が bot を動かすときはプロファイルを、対応が固定でコードと一緒にあるときはポートを使ってください。
各デバイスに固有のプロキシを与える
IP を共有するアカウントは運命も共有します。MAS はデバイスごとに 1 つのプロキシを付け、そのインスタンスのトラフィックをそこに通します。
- プロキシ を開きます。プロキシを追加 で、ゲートウェイアカウント タブか、自前のプロキシ (
http、https、socks5) 用の 別のプロバイダー タブを埋め、追加してテスト をクリックします。 - テストを待ちます。プロキシが応答することを確認し、国を検出します。テスト で後から繰り返せます。
- 割り当て をクリックしてデバイスを選ぶか、デバイスグループ でデバイスカードを開き、プロキシ でプロキシを選びます。
デバイスカードは実行のたびにプロキシの状態を表示し、実行の Webhook には proxy_exit_ip と proxy_country が入ります。デバイスが持つプロキシは 1 つで、別のものを付けると置き換わります。プロキシ を参照してください。
すべて開始: LDPlayer や BlueStacks での多重起動の同期
グループ上部の すべて開始 をクリックします。MAS はデバイスを 0.5 秒間隔で順番に開始し、それぞれが固有の実行、ログ、終了コードを持ちます。マクロのないデバイスはエラーで飛ばされ、残りは続きます。すべて停止 はグループ内のすべての実行を終えます。各カードの ログ タブはそのデバイスだけを表示し、マクロにランタイム UI があれば ダッシュボード タブに表示されます。
ストレージでデバイスごとの状態を保つ
mas.save、mas.retrieve、mas.clear は、このコンピューター、デバイスのポート、タスク名をキーとします。したがって同じマクロを動かす 2 つのインスタンスは、追加のコードなしで別々のカウンターを保ちます。合計するには、mas.retrieve_all(task_name) がポートごとに 1 項目を machine_id、port、data、updated_at 付きで返します。
TASK = "collector"
mine = mas.retrieve(TASK) # this instance only
everyone = mas.retrieve_all(TASK) # every instance on this computer
total = sum(entry["data"].get("done", 0) for entry in everyone)ストレージ を参照してください。
グループごとの Webhook
いずれかのアカウントが完了または失敗したときに知らせてもらうには、Webhook ページでエンドポイントを追加し、送信するイベント でイベントを選び、イベントの送信元 で 特定のグループ を選んでグループにチェックを入れます。後からグループに追加したデバイスも対象になります。各イベントには device_name、device_port、group_id、status、exit_code が入るので、1 つのエンドポイントでアカウントを見分けられます。Webhook を参照してください。
BlueStacks の bot ファームのリソース上限に注意する
すべてのインスタンスは完全な Android システムです。規模を広げる前に、3 つのことを確認してください:
- インスタンスごとの CPU と RAM。 各インスタンスは、エミュレータのインスタンス設定で設定したコアとメモリを使います。合計し、同じマシンですべてのインスタンスのテンプレートマッチングと OCR を実行する MAS のための余裕を残してください。タップが遅れて落ち始めたら、限界を超えています。
- プランのデバイス数。 プランの大きさは、自分のデバイスを同時に何台動かせるかで決まります。すべて開始 はプランが許す台数だけ実行します。お支払い と 料金ページ を参照してください。
- スケジュールジョブ。 スケジューラーは同時に最大 20 個のジョブを、ポートごとに 1 つ実行します。
テンプレートを見失う多くのインスタンスより、きれいに動く少ないインスタンスの方が優れています。
グループをスケジュールする
スケジューラーはジョブごとに 1 つのポートを対象にするので、グループのスケジュールはデバイスごとに 1 つのジョブです。
- スケジューラー を開き、新しいスケジュールを作成 をクリックします。
- マクロ を選び、エミュレータポート で スキャン をクリックして最初のインスタンスを選びます。
- 日付、時刻、繰り返し を設定し、スケジュールを作成 をクリックします。
- 各ポートについて繰り返します。ジョブには同じ時刻を与えてください。ポートが違えば衝突しません。
スケジュール実行は各デバイスカードに保存された引数、またはデバイスが従うプロファイルを使うので、アカウントごとの値が引き継がれます。アプリは開いたままにする必要があります。スケジューラー と ループガイド を参照してください。
完全な例
このマクロは自分のポートを読み、アカウントの設定を選び、ポートごとのカウンターを保ち、最後にすべてのインスタンスの合計を記録します。ポートと画像 ID を自分のものに置き換えてください。
import random
import sys
import time
import mas
images = mas.images({
"collect": 501,
"close_popup": 502,
})
SETTINGS = { # per instance, keyed by the emulator's adb port
5555: {"account": "main", "rounds": 20},
5557: {"account": "alt-1", "rounds": 10},
5559: {"account": "alt-2", "rounds": 10},
}
DEFAULT = {"account": "unknown", "rounds": 5}
TASK = "collector"
TIME_BUDGET_S = 15 * 60
def main():
port = mas.get_current_device_port()
settings = SETTINGS.get(port, DEFAULT)
account = settings["account"]
mas.log(f"Port {port}: account {account}, {settings['rounds']} rounds")
done = mas.retrieve(TASK).get("done", 0)
started = time.monotonic()
misses = 0
while done < settings["rounds"]:
if time.monotonic() - started > TIME_BUDGET_S:
mas.log(f"{account}: time budget reached", level="warning")
break
popup = mas.find_object(images.close_popup)
if popup:
mas.click(popup.x, popup.y, delay_ms=800)
continue
button = mas.find_object_retry(images.collect, total_tries=3, time_sleep=2.0)
if button is None:
misses += 1
if misses >= 5:
mas.log(f"{account}: five misses, giving up", level="error")
sys.exit(2)
continue
misses = 0
mas.click(button.x, button.y, delay_ms=1000)
done += 1
mas.save(TASK, {"done": done, "account": account})
time.sleep(random.uniform(0.8, 2.5))
total = sum(entry["data"].get("done", 0) for entry in mas.retrieve_all(TASK))
mas.log(f"{account}: {done} rounds done; {total} across all instances")
mas.webhook("account.finished", {"account": account, "port": port, "done": done})
if __name__ == "__main__":
main()mas.webhook は、カスタムイベントを購読するエンドポイントに custom.account.finished イベントを送ります。エンドポイントがなければこの行は省いてください。対応表が大きくなったら、引数フォームに移し、辞書の代わりに args.<tab>.<key> を読みます。
うまくいかないとき
Port is already in use
グループ内の別のデバイスがそのポートを持っています。各ポートは 1 度しか追加できません。古い項目を削除するか、もう一方のインスタンスのポートを選んでください。
1 つのインスタンスは動くが、残りは Connecting のまま
残りのインスタンスは ADB がオフ、まだ起動中、またはエミュレータの範囲外のポートで待ち受けています。各インスタンスの設定を開き、ADB とポートを確認して、デバイスを追加 で 更新 をクリックします。ポートが上の表の外にあるなら、カスタムポート を使います。ADB トラブルシューティング を参照してください。
テンプレートが 1 つのインスタンスでしか一致しない
そのインスタンスの解像度か DPI が違います。テンプレートマッチングはピクセルベースです。エミュレータのインスタンス設定で、すべてのインスタンスを取り込み時の解像度にして再起動してください。残りは 画像認識ガイド で説明しています。
すべてのインスタンスが 1 つのカウンターを共有する
スクリプトが mas.save に明示的な port か machine_id を渡しているか、ストレージの代わりにディスク上のファイルを使っています。既定のまま mas.save(TASK, data) を呼んでください。現在のポートは自動で追加されます。
100%リスクのない自動化ツールは存在しないため、自動化は責任を持って、ご自身の判断で行ってください。
次のステップ
関連ページ
ありがとうございます。誤りがあればDiscordでお知らせください。
質問がありますか? Discordで質問する