Buscar

Guias

Multi-instância de emulador Android: farm com grupos

Farm multi-instância de emulador Android no MAS: adicione cada instância do BlueStacks ou LDPlayer pela porta, agrupe-as e dê a cada um seu perfil e proxy.

  • Windows
  • Mac
  • Emulador
  • Studio
  • SDK Python
Intermediário Atualizado em 8 min de leitura
Nesta página
  1. Antes de começar
  2. Cada instância de um emulador Android multi-instância é um dispositivo
  3. Criar um grupo de dispositivos
  4. Dê a cada dispositivo os próprios argumentos
  5. Dê a cada dispositivo o próprio proxy
  6. Iniciar todos: sincronização multi-instância no LDPlayer ou BlueStacks
  7. Mantenha o estado por dispositivo com o armazenamento
  8. Webhooks por grupo
  9. Fique de olho nos limites de recursos de uma farm de bots no BlueStacks
  10. Agende o grupo
  11. Um exemplo completo
  12. O que pode dar errado
  13. A porta já está em uso
  14. Uma instância roda, as outras ficam em Conectando
  15. Os templates correspondem em uma única instância
  16. Toda instância compartilha um contador

Uma macro, cinco contas, um clique: isso é farm multi-instância de emulador Android. O Macro Automation Studio (MAS) trata toda instância de emulador como um dispositivo separado. Um grupo de dispositivos então roda a mesma macro em todas elas, com argumentos por dispositivo, um proxy para cada uma e um armazenamento que nunca mistura contadores. Este guia monta essa configuração no BlueStacks, LDPlayer, MuMu Player ou MEmu. Ele é para quem roda mais de uma conta.

Antes de começar

  • O MAS está instalado e você fez login com um plano cuja contagem de dispositivos cobre as instâncias que você quer rodar ao mesmo tempo. Veja Cobrança.
  • O gerenciador de multi-instâncias do emulador criou as instâncias e cada uma tem o ADB ativado. Os guias do BlueStacks, do LDPlayer, do MuMu Player e do MEmu mostram onde ficam a opção e a porta.
  • Toda instância usa a mesma resolução e o mesmo DPI daquela em que você capturou os templates.
  • A macro funciona em uma instância a partir do Code Editor. Veja o guia de loops.

Cada instância de um emulador Android multi-instância é um dispositivo

Uma instância de emulador escuta o adb na própria porta TCP local. O MAS encontra as instâncias escaneando os processos em execução e mantendo as portas dentro da faixa conhecida de cada emulador. Duas janelas do BlueStacks aparecem, portanto, como duas entradas na lista Porta. O dispositivo é a porta; o grupo é a lista de portas.

EmuladorPortas que o MAS aceita
BlueStacks5555 a 8500
LDPlayerPortas ímpares de 5555 a 5599
MuMu PlayerPortas ímpares de 5555 a 5599, 7555, 16384 a 16576, 26624 a 27264
MEmu21503 e toda porta terminada em 3 acima dela, abaixo de 30000

Mantenha toda instância aberta enquanto a adiciona; uma instância parada não tem porta para encontrar. A página Dispositivos tem as regras completas de descoberta.

Criar um grupo de dispositivos

  1. Abra Grupos de dispositivos e clique em Criar novo grupo.
  2. Digite um Nome, mantenha o tipo Local e clique em Criar grupo.
  3. Abra o grupo e clique em Adicionar dispositivo.
  4. Digite um Nome do dispositivo que diga qual conta é, por exemplo farm-alt-2.
  5. Escolha a porta da instância em Porta. Clique em Atualizar se ela não aparecer, ou escolha Porta personalizada e digite-a.
  6. Clique em Adicionar dispositivo e repita para cada instância.
  7. Em cada card de dispositivo, escolha a macro no seletor Macro.

Uma porta pode pertencer a um único dispositivo. Adicioná-la duas vezes falha com “Port is already in use”. Veja Grupos de dispositivos.

Dê a cada dispositivo os próprios argumentos

A maioria dos bots precisa de um valor que muda por conta: um nome, um alvo, um número de rodadas. Há duas formas de passá-lo.

Perfis de configurações (sem mudar o código). Se a macro tem um formulário de argumentos do UI Builder, cada card de dispositivo tem Editar argumentos. A caixa de diálogo traz uma barra Perfil: informe os valores, escolha Salvar os valores atuais como novo perfil, dê um nome e clique em Criar perfil. Um dispositivo segue um perfil, e editar o perfil atualiza todo dispositivo que o segue na próxima execução. O “Padrão” sempre existe e não pode ser excluído. Veja Perfis de configurações e UI Builder.

A porta no código. O script pode perguntar em qual instância está e escolher as próprias configurações. Isso não precisa de formulário e é o que o exemplo do final faz.

python
import mas

port = mas.get_current_device_port()   # 5555, 5557, 5559 ...

Use perfis quando os valores mudam com frequência ou outra pessoa roda o bot; use a porta quando o mapeamento é fixo e vive junto com o código.

Dê a cada dispositivo o próprio proxy

Contas que compartilham um IP compartilham o mesmo destino. O MAS anexa um proxy por dispositivo e roteia o tráfego daquela instância por ele.

  1. Abra Proxies. Em Adicionar um proxy, preencha a aba Conta do gateway, ou a aba Outro provedor para um proxy seu (http, https ou socks5), e clique em Adicionar e testar.
  2. Aguarde o teste. Ele confirma que o proxy responde e detecta o país; Testar o repete depois.
  3. Clique em Atribuir e escolha o dispositivo, ou abra o card do dispositivo em Grupos de dispositivos e escolha o proxy em Proxy.

O card do dispositivo mostra o estado do proxy a cada execução, e os webhooks de execução carregam proxy_exit_ip e proxy_country. Um dispositivo tem um proxy; anexar outro substitui o anterior. Veja Proxies.

Iniciar todos: sincronização multi-instância no LDPlayer ou BlueStacks

Clique em Iniciar todos no topo do grupo. O MAS inicia os dispositivos um após o outro, com meio segundo de intervalo, cada um com a própria execução, o próprio log e o próprio código de saída. Um dispositivo sem macro é pulado com um erro e o resto continua. Parar todos encerra toda execução do grupo. A aba Logs de cada card mostra só aquele dispositivo, e a aba Dashboard mostra a interface de execução dele se a macro tiver uma.

Mantenha o estado por dispositivo com o armazenamento

mas.save, mas.retrieve e mas.clear são indexados por este computador, pela porta do dispositivo e por um nome de tarefa. Duas instâncias rodando a mesma macro mantêm, portanto, contadores separados sem código extra. Para somá-los, mas.retrieve_all(task_name) retorna uma entrada por porta com machine_id, port, data e updated_at.

python
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)

Veja Armazenamento.

Webhooks por grupo

Para ser avisado quando qualquer conta terminar ou falhar, adicione um endpoint na página Webhooks, escolha os eventos em Me envie, e em Me envie eventos de escolha Grupos específicos e marque o grupo. Os dispositivos que você adicionar ao grupo depois também ficam cobertos. Cada evento carrega device_name, device_port, group_id, status e exit_code, então um único endpoint consegue distinguir as contas. Veja Webhooks.

Fique de olho nos limites de recursos de uma farm de bots no BlueStacks

Toda instância é um sistema Android completo. Antes de escalar, confira três coisas:

  • CPU e RAM por instância. Cada instância consome os núcleos e a memória definidos nas configurações de instância do emulador. Some tudo e deixe folga para o MAS, que roda o template matching e o OCR de toda instância na mesma máquina. Quando os toques começam a atrasar, você passou do limite.
  • Dispositivos do seu plano. Um plano é dimensionado por quantos dos seus dispositivos podem rodar ao mesmo tempo. Iniciar todos roda quantos o plano permitir; veja Cobrança e a página de preços.
  • Jobs agendados. O Agendador roda até 20 jobs de uma vez, um por porta.

Menos instâncias rodando limpas valem mais do que muitas instâncias errando templates.

Agende o grupo

O Agendador tem uma porta como alvo por job, então um agendamento de grupo é um job por dispositivo.

  1. Abra o Agendador e clique em Criar novo agendamento.
  2. Escolha a Macro, clique em Escanear em Porta do emulador e escolha a primeira instância.
  3. Defina Data, Hora e Recorrência, depois clique em Criar agendamento.
  4. Repita para cada porta. Dê aos jobs o mesmo horário; portas diferentes nunca colidem.

As execuções agendadas usam os argumentos salvos em cada card de dispositivo, ou o perfil que o dispositivo segue, então os valores por conta são mantidos. O app precisa ficar aberto. Veja Agendador e o guia de loops.

Um exemplo completo

A macro lê a própria porta, escolhe as configurações da conta, mantém um contador por porta e registra no fim o total de todas as instâncias. Troque as portas e os IDs de imagem pelos seus.

python
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 envia um evento custom.account.finished aos endpoints inscritos em eventos personalizados; tire a linha se você não tiver nenhum. Quando o mapeamento crescer, mova-o para um formulário de argumentos e leia args.<tab>.<key> em vez do dicionário.

O que pode dar errado

A porta já está em uso

Outro dispositivo em um dos seus grupos é dono dessa porta. Cada porta pode ser adicionada uma vez; remova a entrada antiga ou escolha a porta da outra instância.

Uma instância roda, as outras ficam em Conectando

As outras instâncias estão com o ADB desligado, ainda estão iniciando, ou escutam em portas fora da faixa do emulador. Abra as configurações de cada instância, confirme o ADB e a porta, e clique em Atualizar em Adicionar dispositivo. Se a porta fica fora da tabela acima, use Porta personalizada. Veja Solução de problemas de ADB.

Os templates correspondem em uma única instância

Aquela instância tem outra resolução ou DPI. O template matching é baseado em pixels; coloque toda instância na resolução da captura nas configurações de instância do emulador e reinicie. O guia de reconhecimento de imagem explica o resto.

Toda instância compartilha um contador

O script passa um port ou machine_id explícito a mas.save, ou usa um arquivo em disco em vez do armazenamento. Chame mas.save(TASK, data) com os padrões; a porta atual é adicionada para você.

Nenhuma ferramenta de automação é 100% livre de riscos, por isso automatize com responsabilidade e a seu próprio critério.

Próximos passos

Páginas relacionadas

Esta página foi útil?

Dúvidas? Pergunte no Discord