Construindo um bot com Python RPA para interagir com sistemas desktop

Morganna - Sep 20 '23 - - Dev Community

Você já deve conhecer ferramentas e frameworks que podem te ajudar a construir automações para interagir com sistemas Web. Mas e quando se trata de sistemas desktop, como você faz? Vim te mostrar como utilizar o framework Open Source da BotCity com diversas funcionalidades para você construir a sua automação com Python RPA.

Preparando o ambiente de desenvolvimento

  • Crie a sua conta gratuita na plataforma da BotCity;
  • Acompanhe o passo a passo da instalação nas orientações da documentação de pré-requisitos e da instalação do SDK BotCity Studio;
  • Instale o Sicalc (caso queira seguir o tutorial com o mesmo programa de exemplo utilizado).
    • o Sicalc desktop é utilizado de maneira offline, então não será gerada uma Nota Fiscal válida;
    • o Sicalc funciona para sistema operacional Windows, contudo todo o processo e uso do framework pode ser aplicado também para distribuições Linux e MacOS sem problemas;
    • ao abrir o Sicalc pela primeira vez, será solicitado um código de município. Para o nosso exemplo, vamos colocar o 7107 que representa São Paulo, mas poderia ser qualquer outro.

Primeiros passos do desenvolvimento do nosso robô

Criando o projeto a partir do template da BotCity

No terminal do seu computador, dentro da pasta em que você deseja criar o projeto, execute o seguinte comando para instalarmos o pacote cookiecutter (porque os templates oferecidos foram criados a partir dele).

Para instalarmos o pacote do cookiecutter, vamos executar o seguinte comando:

python -m pip install --upgrade cookiecutter
Enter fullscreen mode Exit fullscreen mode

Para criarmos um projeto usando o modelo, vamos invocar o cookiecutter e fornecer como argumento a URL do repositório onde os templates da BotCity estão localizados:

python -m cookiecutter https://github.com/botcity-dev/bot-python-template/archive/v2.zip
Enter fullscreen mode Exit fullscreen mode

Durante a execução deste comando, você precisará informar duas coisas:

  • project_type: refere-se ao tipo de projeto que deseja criar. O template fornecerá algumas opções, mas neste caso, vamos escolher o número 1, pois vamos construir um bot Desktop;
  • bot_id: refere-se a uma identificação que você deseja dar para o seu projeto. Neste exemplo, chamaremos de bot-sicalc.

Após o término do processo acima, uma nova pasta chamada bot-sicalc estará disponível. Você pode entender um pouco mais sobre a estrutura e como ele funciona com as orientações na documentação.

Instalando as dependências do seu projeto

Normalmente, projetos de desenvolvimento podem ter dependências como os frameworks utilizados, pacotes importantes, entre outros. O nosso também tem dependências e você poderá identificá-las no arquivo requirements.txt. Você notará que há pelo menos essas duas:

botcity-framework-core # framework de desenvolvimento da automação
botcity-maestro-sdk # API do BotCity Maestro para orquestração da automação

Enter fullscreen mode Exit fullscreen mode

Antes de rodar o seu projeto, é importante fazermos a instalação dessas dependências. E para isso, devemos executar o seguinte comando:

pip install --upgrade -r requirements.txt
Enter fullscreen mode Exit fullscreen mode

Primeira execução do nosso robô

Se você entrar no arquivo bot.py, perceberá que já temos um código pré-pronto e alguns comentários com orientações importantes sobre como fazer alguns dos próximos passos.

Entenda o que o código está fazendo

Identifique as linhas com os comandos abaixo. Elas estão importando as bibliotecas que mencionamos do arquivo requirements.txt para que consiga utilizá-las no seu código.

from botcity.core import DesktopBot
from botcity.maestro import *

Enter fullscreen mode Exit fullscreen mode

E nas linhas abaixo, estamos criando um objeto para o bot com o framework Desktop e pedindo para ele abrir um navegador no site da BotCity.

bot = DesktopBot()
bot.browse("<http://www.botcity.dev>")

Enter fullscreen mode Exit fullscreen mode

Execute o robô

Para ver o robô sendo executado, você pode fazer isso pela IDE que estiver utilizando ou na linha de comando com o seguinte:

python bot.py

Enter fullscreen mode Exit fullscreen mode

Deu certo? Abriu o navegador do seu computador com o site da BotCity? Aqui está um exemplo de qual seria o resultado esperado após essa execução:

Print da tela inicial do site da BotCity.

💡 Uma dica interessante é você testar se o que está acontecendo é o esperado. Tente fazer essa prática de testar aos poucos para você entender o que está acontecendo. Isso também facilitará no entendimento caso algum erro ocorra.

Como lidar com os erros

Caso não tenha funcionado de primeira, não se preocupe. É normal você passar por alguns erros quando está desenvolvendo algo pela primeira vez ou aprendendo algo do zero. Te convido a acompanhar este post sobre alguns erros que podem acontecer e te encorajar a compartilhar os erros que você teve e como os resolveu.

Caso esteja com alguma outra dificuldade no desenvolvimento, fique à vontade para entrar em nosso fórum ou em nossa comunidade no slack para pedir ajuda e tirar suas dúvidas.

Desenvolvendo o robô desktop

Para esse desenvolvimento, vamos utilizar o BotCity Studio, que através de visão computacional, nos ajudará com o mapeamento dos itens na tela do sistema utilizado para que nosso robô possa interagir com ele.

Carregando o projeto BotSicalc no BotCity Studio

Mantenha a sua IDE aberta com o seu projeto. Abra também o BotCity Studio e, no menu superior, escolha a opção "File" e, em seguida, "Load Project".

print do menu file aberto dentro do BotCity Studio mostrando a opção

Uma nova janela se abrirá e, nela, você deverá clicar em "browse" e identificar onde está a pasta do seu projeto.

print da janela

Em seguida, identifique o arquivo com extensão .botproj. Selecione este arquivo para o BotCity Studio carregar o seu projeto. No caso deste exemplo, o arquivo será “bot-sicalc.botproj”. Após isso, clique em "Open" e, em seguida, "Launch". Pronto, você já tem seu projeto carregado no BotCity Studio.

Prosseguindo no desenvolvimento

Para os próximos passos, vamos manter as duas ferramentas abertas, a sua IDE e o BotCity Studio, para que os códigos sejam sincronizados em ambas as plataformas.

Até este momento, mantivemos apenas o seguinte código no meu arquivo "bot.py". Perceba que deletamos a linha bot.browse("http://www.botcity.dev"), pois ela não será mais necessária.

# Import for the Desktop Bot
from botcity.core import DesktopBot

# Import for integration with BotCity Maestro SDK
from botcity.maestro import *

# Disable errors if we are not connected to Maestro
BotMaestroSDK.RAISE_NOT_CONNECTED = False

def main():

    bot = DesktopBot()


def not_found(label):
    print(f"Element not found: {label}")

if __name__ == '__main__':
    main()
Enter fullscreen mode Exit fullscreen mode

Ao salvar esse código na minha IDE, ao clicar novamente no BotCity Studio, você perceberá que também foi atualizado.

Abaixo da linha bot = DesktopBot(), vamos adicionar o comando execute para o robô abrir o Sicalc, conforme código abaixo:

bot.execute(r"C:\Program Files (x86)\Programas RFB\Sicalc Auto Atendimento\SicalcAA.exe")
Enter fullscreen mode Exit fullscreen mode

Uma dica interessante é você testar se o que está acontecendo é o esperado. Neste momento, por exemplo, podemos salvar o código e executar o robô pela IDE para verificarmos se, de fato, o comando funcionará. Tente fazer essa prática de testar aos poucos para você entender o que está acontecendo. Isso também facilitará no entendimento caso algum erro ocorra.

Se essa etapa funcionar, o robô executará e o Sicalc ficará nessa tela:

print da tela inicial do sicalc aberta

💡 Antes de seguir em frente, lembre-se de deixar o cursor logo abaixo da linha de código que o bot abre o Sicalc no BotCity Studio. Isso é porque ele vai começar a gerar código para você utilizar em seu projeto. E o código será adicionado exatamente onde o cursor estiver posicionado.

Identificando pop-up da tela inicial

Ao executarmos o aplicativo Sicalc pela primeira vez, será exibido um pop-up contendo um aviso. A tarefa será identificarmos essa janela e fechá-la logo em seguida.

A estratégia que vamos utilizar é procurar por uma âncora e realizar um clique relativo no botão Continuar.

Voltando ao BotCity Studio, no arquivo bot.py posicionamos o cursor na linha onde o código deve ser gerado.

Na aba UI, clicamos próximo ao elemento que queremos identificar e a ferramenta dará um zoom para selecionarmos o elemento. A seleção do nosso recorte é feita com o mouse, clicando e arrastando até selecionar dessa maneira:

print da tela esclarecimento ao contribuinte e a janela solicitando as informações de nome, ação e modo

💡 Se o zoom não estiver adequado para você fazer a seleção necessária, basta pressionar a tecla esc no seu teclado e refazer o clique próximo ao elemento.

Após selecionado, vamos preencher os campos Name com o valor "popup-esclarecimento" e Action com o valor "Click_relative". O campo "mode" deve ser mantido com a opção "Image" selecionada. Em seguida, clicamos no botão Submit.

print da tela para preenchimento de nome e ação

Após clicar em Submit, ao arrastar o mouse, você perceberá que uma linha vermelha acompanhará o movimento. Nós devemos dizer para o BotCity Studio onde deverá ser o clique relativo. Neste caso, será o botão "Continuar". Então arrastamos o cursor do mouse até esse botão e clicamos nele.

Com essa etapa concluída, o seguinte trecho de código será gerado pelo BotCity Studio:

# Abre o aplicativo do SiCalc
bot.execute(path_sicalc)

if not bot.find( "popup-esclarecimento", matching=0.97, waiting_time=10000):
    not_found("popup-esclarecimento")
bot.click_relative(195, 211)
Enter fullscreen mode Exit fullscreen mode

Lembre-se de salvar o código no BotCity Studio, que pode ser pelo atalho "ctrl + s". Isso fará com que a sua IDE também seja atualizada com o novo código gerado.

Ao rodarmos novamente esse código pela IDE, depois de abrir o aplicativo Sicalc, o bot realizará o clique relativo no elemento que foi selecionado acima. A partir disso, conseguimos continuar o processo de preenchimento da DARF.

Selecionando opções do menu

No aplicativo do Sicalc, precisaremos acessar a opção Funções do menu e, em seguida, a opção Preenchimento de DARF. Então devemos tirar um novo print da tela do Sicalc e, no BotCity Studio, podemos fazer o recorte desses elementos.

Vamos começar pelo item "Funções". E para essa opção, vamos dar o nome funcoes e a action será click. A opção mode deve continuar como image.

print mostrando em destaque a parte de funções selecionada com nome e ação preenchidos conforme texto do tutorial

Com o sub-menu de opções de Funções aberto, vamos tirar um novo print para fazermos a seleção e ação Click na opção Preenchimento de DARF, chamando-a de preenchimento-darf.

print mostrando em destaque a parte de preenchimento de DARF selecionada

O código gerado pelo BotCity Studio será parecido com o código abaixo:

if not bot.find( "funcoes", matching=0.97, waiting_time=10000):
    not_found("funcoes")
bot.click()

if not bot.find( "preenchimento-darf", matching=0.97, waiting_time=10000):
    not_found("preenchimento-darf")
bot.click()
Enter fullscreen mode Exit fullscreen mode

Preenchendo do formulário inicial

Após a etapa anterior, será aberto um formulário inicial onde precisaremos preencher somente o código da receita.

Novamente, vamos tirar um novo print da tela atualizada para fazermos a seleção do elemento correto no BotCity Studio.

Nesse caso, vamos encontrar a âncora do input Cód. Receita e fazer um clique relativo dentro do campo, que fica logo na frente para ser preenchido:

print com a tela em destaque para a parte de código da receira selecionada e a janela para preenchimento de nome e ação

Após encontrar e clicar no campo referente a esse elemento, utilizamos o comando paste() para inserir nosso dado. Em seguida vamos utilizar o comando tab() para avançarmos para o próximo formulário.

Você pode adicionar o código com o comando paste() e com o comando tab() diretamente no BotCity Studio e salvar para atualizar na sua IDE, ou adicionar diretamente pela IDE. Apenas lembre-se de salvar o código para ambas as ferramentas seguirem atualizadas.

Abaixo, o exemplo de como poderá ficar esse trecho do código:

if not bot.find( "codigo-receita", matching=0.97, waiting_time=10000):
    not_found("codigo-receita")
bot.click_relative(128, 10)

# Inserindo no campo um código fictício
bot.paste("5629")

# Tecla "tab" avança para o próximo formulário
bot.tab()
Enter fullscreen mode Exit fullscreen mode

Preenchendo os dados da DARF

Ao executarmos o código acima, será aberto um segundo formulário. E nele, devemos inserir os demais dados da DARF. Neste momento, a tela será parecida com essa:

print da tela do sicalc para preenchimento de informações conforme descrito no tutorial

Atualizando o print da tela no BotCity Studio, vamos precisar encontrar os elementos referentes ao período de apuração (campo PA) e ao valor do documento (campo Valor em Reais) e fazer um clique relativo nos seus respectivos campos:

print da tela do sicalc com destaque no campo PA

print da tela do sicalc com destaque no campo valor em reais

E da mesma forma que fizemos anteriormente, vamos utilizar o comando paste() do framework para nos ajudar a digitar o valor dentro dos campos que estamos preenchendo neste momento. Perceba como o código ficará nessa etapa:

if not bot.find( "periodo-apuracao", matching=0.97, waiting_time=10000):
    not_found("periodo-apuracao")
bot.click_relative(15, 25)
# Inserindo PA
bot.paste("310120")

if not bot.find( "valor", matching=0.97, waiting_time=10000):
    not_found("valor")
bot.click_relative(17, 27)
# Inserindo valor
bot.paste("10000")
Enter fullscreen mode Exit fullscreen mode

O próximo passo é clicarmos no botão Calcular, para conseguirmos acessar o formulário final. Temos duas formas de resolver essa etapa. A primeira delas seria adicionar o comando enter(), pois essa ação no teclado de apertar a tecla enter, após o preenchimento dos campos, aciona o botão Calcular.

bot.enter()
Enter fullscreen mode Exit fullscreen mode

Outra forma é seguir pela visão computacional e apoio do BotCity Studio. Então tiramos um novo print, selecionamos o botão Calcular e informamos que a ação deverá ser a de click.

print da tela do sicalc com destaque no botão calcular e a janela para preencher o nome do botão e a ação de clique

if not bot.find( "calcular", matching=0.97, waiting_time=10000):
    not_found("calcular")
bot.click()
Enter fullscreen mode Exit fullscreen mode

Preenchendo formulário final

Após o processo de cálculo ser finalizado, precisamos acessar o formulário final. Para isso, vamos clicar no botão DARF:

print sicalc com destaque onde está o botão DARF e a janela para preencher o nome e ação para o botão

if not bot.find( "botao-darf", matching=0.97, waiting_time=10000):
    not_found("botao-darf")
bot.click()
Enter fullscreen mode Exit fullscreen mode

Com o formulário final aberto, vamos atualizar o print da tela no BotCity Studio para fazermos a seleção dos últimos elementos:

print do sicalc mostrando o calculo feito e a janela para preencher nome, telefone e outros dados

Para essa etapa, vamos seguir utilizando a mesma estratégia das etapas anteriores, procurando pela âncora e fazendo um clique relativo no campo que precisamos preencher.

Os dados que precisamos preencher nesse último formulário serão:

  • Nome: Petrobras
  • Telefone: 1199991234
  • CNPJ: 33000167000101
  • Referência: 0

Com todas as âncoras mapeadas, o código gerado será semelhante a esse:

if not bot.find( "nome", matching=0.97, waiting_time=10000):
    not_found("nome")
bot.click_relative(0, 24)

# Inserindo nome no campo
bot.paste("Petrobras")

if not bot.find( "telefone", matching=0.97, waiting_time=10000):
    not_found("telefone")
bot.click_relative(1, 27)

# Inserindo telefone no campo
bot.paste("1199991234")

if not bot.find( "cnpj", matching=0.97, waiting_time=10000):
    not_found("cnpj")
bot.click_relative(123, 9)

# Inserindo CNPJ no campo
bot.paste("33000167000101")

if not bot.find( "referencia", matching=0.97, waiting_time=10000):
    not_found("referencia")
bot.click_relative(121, 8)

# Inserindo referência no campo
bot.paste("0")
Enter fullscreen mode Exit fullscreen mode

Salvando o arquivo

O último passo é salvarmos o arquivo da DARF que será gerado. Ainda na tela do último formulário exibido, após preencher os dados vamos clicar no botão Imprimir:

print do sicalc com o botão imprimir em destaque e a janela para configurar a ação de clique

if not bot.find( "imprimir", matching=0.97, waiting_time=10000):
    not_found("imprimir")
bot.click()
Enter fullscreen mode Exit fullscreen mode

Clicando no botão, será aberto a janela do gerenciador de arquivos do Windows, caso não tenha diretamente uma impressora configurada:

print da tela para salvar o arquivo pdf da DARF

Neste caso, vamos encontrar a referência dessa janela e clicar para que ela fique em foco:

print com zoom na tela

Após isso, podemos utilizar o paste() para informar qual será o caminho do arquivo e o enter() para salvar. Abaixo temos o exemplo de como poderá ficar o código:

if not bot.find( "janela-salvar", matching=0.97, waiting_time=10000):
    not_found("janela-salvar")
bot.click()

# Inserindo o caminho do arquivo
bot.paste(r"C:\Users\username\Documents\DARF.pdf")
bot.enter()
Enter fullscreen mode Exit fullscreen mode

Finalizando o processo

Após salvar o arquivo, nosso processo está finalizado!

Podemos agora utilizar o comando wait() para aguardar 2 segundos e garantir que tudo foi salvo e depois o comando alt_f4() para fecharmos o formulário e a janela do Sicalc.

# Aguarda 2 segundos
bot.wait(2000)

# Fechando janela do formulário
bot.alt_f4()

# Fechando app do SiCalc
bot.alt_f4()
Enter fullscreen mode Exit fullscreen mode

💡 Essa estratégia do comando wait() pode ser útil em algumas ocasiões, quando algum processo ou comando pode levar um tempo para acontecer ou atualizar antes de ir para a próxima etapa do processo. Então analise se no seu projeto isso pode te ajudar e utilize da maneira que for melhor para você.

Código final

Caso queira validar como o código final deste tutorial poderá ficar, segue abaixo o conteúdo do arquivo bot.py do projeto:

def main():
    bot = DesktopBot()

    # Implement here your logic...
    # Caminho onde está o executável SiCalc
    path_sicalc = r"C:\Program Files (x86)\Programas RFB\Sicalc Auto Atendimento\SicalcAA.exe"

    # Abre o aplicativo do SiCalc
    bot.execute(path_sicalc)

    if not bot.find( "popup-esclarecimento", matching=0.97, waiting_time=10000):
        not_found("popup-esclarecimento")
    bot.click_relative(195, 211)

    if not bot.find( "funcoes", matching=0.97, waiting_time=10000):
        not_found("funcoes")
    bot.click()

    if not bot.find( "preenchimento-darf", matching=0.97, waiting_time=10000):
        not_found("preenchimento-darf")
    bot.click()

    if not bot.find( "codigo-receita", matching=0.97, waiting_time=10000):
        not_found("codigo-receita")
    bot.click_relative(128, 10)

    # Inserindo no campo um código fictício
    bot.paste("5629")

    # Tecla "tab" avança para o próximo formulário
    bot.tab()

    if not bot.find( "periodo-apuracao", matching=0.97, waiting_time=10000):
        not_found("periodo-apuracao")
    bot.click_relative(15, 25)
    # Inserindo PA
    bot.paste("310120")

    if not bot.find( "valor", matching=0.97, waiting_time=10000):
        not_found("valor")
    bot.click_relative(17, 27)
    # Inserindo valor
    bot.paste("10000")

    if not bot.find( "calcular", matching=0.97, waiting_time=10000):
        not_found("calcular")
    bot.click()

    if not bot.find( "botao-darf", matching=0.97, waiting_time=10000):
        not_found("botao-darf")
    bot.click()

    if not bot.find( "nome", matching=0.97, waiting_time=10000):
        not_found("nome")
    bot.click_relative(0, 24)
    # Inserindo nome
    bot.paste("Petrobras")

    if not bot.find( "telefone", matching=0.97, waiting_time=10000):
        not_found("telefone")
    bot.click_relative(1, 27)
    # Inserindo telefone
    bot.paste("1199991234")

    if not bot.find( "cnpj", matching=0.97, waiting_time=10000):
        not_found("cnpj")
    bot.click_relative(123, 9)
    # Inserindo CNPJ
    bot.paste("33000167000101")

    if not bot.find( "referencia", matching=0.97, waiting_time=10000):
        not_found("referencia")
    bot.click_relative(121, 8)
    # Inserindo referência
    bot.paste("0")

    if not bot.find( "imprimir", matching=0.97, waiting_time=10000):
        not_found("imprimir")
    bot.click()

    if not bot.find( "janela-salvar", matching=0.97, waiting_time=10000):
        not_found("janela-salvar")
    bot.click()

    # Inserindo path do arquivo
    bot.paste(r"C:\Users\username\Documents\DARF.pdf")
    bot.enter()

    # Aguarda 2 segundos
    bot.wait(2000)

    # Fechando janela do formulário
    bot.alt_f4()

    # Fechando app do SiCalc
    bot.alt_f4()

def not_found(label):
    print(f"Element not found: {label}")

if __name__ == '__main__':
    main()
Enter fullscreen mode Exit fullscreen mode

Para explorar mais comandos do framework desktop

Tem vários outros comandos que você pode explorar e utilizar para construir suas automações desktop. Acompanhe pelo link da documentação.

Compartilhe com a comunidade o seu projeto

Após construir a sua automação, que tal compartilhar com a comunidade o que aprendeu e o robô que você construiu? Basta compartilhar com o repositório de robôs da comunidade.

. . . . . . . . . . . . . . . . . . .