Filmes de Porto Alegre no Cinema em Poa com BotCity
Por que a BotCity?
A BotCity é uma empresa brasileira, que teve a ideia de criar um framework que junta diversos tipos de automações em apenas um framework, mas mais que isso, oferece um gerenciador gráfico e web para que seja possível criar suas automações e tem soluções que facilitam o monitoramento e gerenciamento das automações usadas.
Isso facilita muito para gerenciar um projeto, pois atualizar um projeto é sempre algo trabalhoso e no caso a preocupação se torna apenas os pacotes da BotCity.
No caso, vamos usar para verificar os filmes que estão sendo divulgados no site do Cinema em POA.
0 - Preparando o ambiente
1 - Código Completo
2 - Como executar pela BotCity?
3 - Conclusão
0 - Preparando o ambiente
Antes de tudo, precisamos criar nosso ambiente virtual, utilizando o comando virtualenv e então ativá-lo:
virtualenv --python=3 venv
source venvDepois disso, podemos clonar o repositório onde o código está:
git clone https://github.com/lcsvillela/cinema-em-poa-botcity.gitE então instalar no nosso ambiente venv as dependências:
pip install -r requirements.txt1 - Análise do Código Completo
No trecho abaixo importamos as bibliotecas que iremos utilizar:
1
2
3
4
5
6
7
8
from botcity.plugins.http import BotHttpPlugin
from botcity.plugins.telegram import BotTelegramPlugin
from bs4 import BeautifulSoup as bs
from requests.exceptions import ConnectionError
from datetime import datetime
import os
from botcity.maestro import *
from time import sleep
No código abaixo, criamos uma classe chamada CinemaEmPoa, que tem a sua inicialização definida com três parâmetros, o self que é um objeto que é acessível em toda a classe, a url que iremos utilizar e o token de acesso do Telegram (obviamente este token não funciona, use o seu).
Aproveitamos para declarar as variáveis que precisaremos em algum momento utilizando o self para que sejam globais e também executamos métodos quando a classe é instanciada para que seja executado o bot. Podemos observar a linha 14 extraindo os dados do site do Cinema em Poa, na 15 o método que cria a estrutura da mensagem e por fim o início da execução completa com o método start.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class CinemaEmPoa:
def __init__(
self,
url="https://cinemaempoa.com.br/program",
token="8123421335:ABFwVGLoyMxTpPXWTtG7Ugl136L\_1W8s9wE",
):
self.http = BotHttpPlugin(url)
self.telegram = telegram = BotTelegramPlugin(token=token)
self.page = None
self.message\_films = None
self.films = {}
self.last\_time = None
self.last\_update\_id = self.load\_offset()
self.get\_data()
self.create\_message()
self.start()
O telegram não faz o controle da fila de requisições que o bot recebe, então em alguns frameworks precisamos nós mesmos fazer o controle, salvando o último ID processado em um arquivo, no caso o last_id.data:
1
2
3
4
5
6
7
8
9
def save\_offset(self, offset):
with open("last\_id.data", "w") as f:
f.write(str(offset))
def load_offset(self):
if os.path.exists("last_id.data"):
with open("last_id.data", "r") as f:
return int(f.read())
return None
Aqui apenas pegamos o código da página e colocamos no parser do BeautifulSoup para facilitar a extração futura dos dados:
1
2
3
4
5
6
def get\_page(self):
try:
source = self.http.get().content
self.page = bs(source, "html.parser")
except ConnectionError:
print("error: connection")
Quando abrimos a página do Cinema em POA e vamos na programação, vemos que temos a estrutura de datas e depois filmes do dia, então a ideia aqui é basicamente extrair os blocos que englobam a data e os filmes relacionados naquela data e então iterar com um for para conseguir estruturar a informação em dois níveis: um dicionário tem a chave da data e ele então armazena um vetor de dicionários que tem as informações de cada filme.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def get\_films(self):
_dates = self.page.find_all(class_="col-md-8")
for _date in _dates:
_date_text = _date.find(class_="mb-2 fs-5").getText()
self.films[f"{_date_text}"] = []
_films = _date.find_all(class_="mb-1")
for _film in _films:
_location = _film.getText().strip().split(" ")[-1]
_title_film = _film.getText().strip().split(" ")[1:-1]
_hour = _film.getText().strip().split(":")[0]
_title_film = " ".join(_title_film)
self.films[f"{_date_text}"].append(
{"location": _location, "title": _title_film, "hour": _hour}
)
Como temos a informação dos filmes estruturada, podemos agora organizá-la do jeito que queremos, usando o join podemos juntar todas as strings que temos e ter uma mensagem para o usuário.
1
2
3
4
5
6
7
8
9
10
11
12
def create\_message(self):
self.message_films = ""
for films in self.films.keys():
for film in self.films[f"{films}"]:
location = film["location"]
title = film["title"]
hour = film["hour"]
self.message_films += " ".join(
[films, "-", hour, "-", title, "-", location, "\n"]
)
Aqui temos a execução da get_data, que ao fim da execução, armazena a data de sua execução, que utilizaremos para economizar nossa banda.
Na execução do método bot_telegram, temos na linha 8 o comando que verifica as novas requisições e utiliza o ID que salvamos anteriormente para que não fique repetindo as requisições anteriores.
Na linha 10 verificamos se temos alguma requisição, caso contrário retornamos ao ponto de chamada e não é executado o resto do código, na linha 13, temos um for que iterará por todas as requisições, verificando o seu conteúdo e casando as strings de comando que foram especificadas.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
def get\_data(self):
self.get\_page()
self.get\_films()
self.last\_time = datetime.now()
def bot_telegram(self):
updates = self.telegram.bot.get_updates(offset=self.last_update_id)
if len(updates) == 0:
return
for update in updates:
message = update.message
chat_id = message.chat.id
text = message.text
if text == "/start":
self.telegram.bot.send_message(
chat_id,
"Este é o bot do Cinema em POA feito com o BotCity! Agora você pode ver todos os filmes que passarão na cidade :D\n/filmes - para ver a lista completa de filmes\n/ajuda - veja o que este bot pode fazer!\n\n Mais informações em www.lcsvillela.com",
)
elif text == "/status":
self.telegram.bot.send_message(
chat_id, "O sistema está rodando perfeitamente! 🚀"
)
elif text == "/ajuda":
self.telegram.bot.send_message(
chat_id, "Use /filmes para ver todos os filmes que estão passando!"
)
elif text == "/filmes":
self.telegram.bot.send_message(chat_id, self.message_films)
self.last_update_id = update.update_id + 1
self.save_offset(self.last_update_id)
O inicializador tem este método, que tem um loop indefinido e que verifica se faz mais de um dia que o site do Cinema em POA foi extraído, executa sempre o método do bot do telegram e espera um segundo para o próximo loop.
1
2
3
4
5
6
7
8
def start(self):
while True:
if (datetime.now() - self.last_time).days:
self.get_data()
self.create_message()
self.bot_telegram()
sleep(1)
2 - Como Executar pela BotCity?
3 - Conclusão
A BotCity é uma plataforma completa, que oferece diversos tipos de RPA possíveis em apenas um framework e possibilita o gerenciamento e monitoramento, de forma intuitiva para que usuários possam executar automações existentes. Para mais informações, veja a documentação da BotCity