# Bot do discord para extrair informações de um site e postar em um canal utilizando python

A ideia deste post é compartilhar a base de um script que criei algum tempo atrás para monitorar o site de um jogo e informar o momento exato que os jogadores do clan inimigo entravam e saiam do jogo, avisando qualquer ação no discord do nosso clan.  
*"PS: Nenhuma regra foi quebrada, o próprio jogo já disponibilizava essa informação, apenas automatizei ela para o discord =P."*

Para fins educativos, neste post vamos criar um bot do discord do zero, instalar em um grupo/servidor, deixar ele online e fazer com que ele leia o valor de um livro em um site e poste o valor e a hora extraida em um canal do discord a cada 30 segundos, servindo de base para novos projetos.

**<mark>Para quem quiser pegar o código fonte e testar, o projeto completo está em:</mark>**  
[https://github.com/RonieNeubauer/scrape-discord-bot](https://github.com/RonieNeubauer/scrape-discord-bot)

# Criando um bot no discord

Primeiro acessamos o Discord Developers  
[https://discord.com/developers/applications](https://discord.com/developers/applications)

Criamos um novo bot clicando em:  
**New Application -&gt; Preencher nome do Bot -&gt; Aceitar termos -&gt; Clicar em Create.**

Após ser redirecionado para a página de configurações do bot:

Clicar no menu da esquerda chamado **BOT**, em seguida vamos gerar e guardar o Token para usar futuramente, clicando em:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1724555670192/b333a600-ebf8-4209-b1e8-81abed9012a8.png align="center")

**Reset Token -&gt; Yes, Do It -&gt; Preencher a senha.** Após isso, copiar e guardar o token gerado conforme a imagem abaixo:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1724555820348/b1d75d01-f7fc-4e5c-84f7-bcc650c9a00c.png align="center")

# Instalando o bot em um grupo do discord

Após gerar o token, basta clicar no menu da esquerda em **OAuth2** e selecionar em **OAuth2 URL Generator** somente a opção **Bot**

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1724556212185/ae1afde9-9c14-40e4-b25d-a2563f0fbae3.png align="center")

Com isso abre um novo setor chamado **Bot Permissions**, onde basta selecionar as seguintes permissões necessárias para nosso bot, selecionando somente **Send Message**

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1724556307470/83f1ecea-9f53-44da-b5ad-55fff0140b37.png align="center")

No final da página selecione **Guild Install** e clique em **Copy** para obter o link de instalação

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1724556379154/47f2b2a8-2782-40f0-8d7b-1440dfd0eb22.png align="center")

Acesse o link em qualquer browser, logue no discord caso necessário, selecione o servidor para instalar o bot, clique em **Continuar** e depois **Autorizar**

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1724556574574/1fb96aaa-ab7d-48c0-a789-352196d13c2e.png align="center")

O bot deve aparecer na lista de usuários offline do seu grupo do discord

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1724556720777/9bc0d3e8-d06b-4931-8c99-54a467596f35.png align="left")

Para finalizar vamos crie um canal chamado **book** onde iremos postar o preço do livro que será extraído pelo web scraping consultando uma página web.  
Basta no menu da esquerda em **Canais de Texto** clicar no **\+ -&gt; Selecionr Texto -&gt; Colocar book como nome do canal -&gt; Criar Canal**

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1724557707976/3777f887-f9be-4b4f-908d-fd876886f17d.png align="center")

Pronto, a primeira parte foi finalizada, temos nosso bot do discord instalado em um grupo e um canal onde iremos postar as mensagens automáticas ao ler o site.

# Colocando o bot online

Primeiro de tudo vamos criar um arquivo chamado `requirements.txt` com todas as bibliotecas de python que iremos utilizar no script, e colocar o código abaixo:

```python
aiohttp==3.9.5
asyncio==3.4.3
attrs==23.1.0
beautifulsoup4==4.12.3
discord.py==2.4.0
requests==2.31.0
pytz==2023.3.post1
```

<mark>Considerando que já temos </mark> **<mark>python e pip instalados na máquina</mark>,** abra o terminal e execute o comando abaixo para instalar todas as bibliotecas necessárias

```python
pip install -r requirements.txt
```

Crie um arquivo chamado `bot.py` onde iremos conectar o bot e deixa-lo somente online sem fazer nada.

```python
import discord
import asyncio

TOKEN = 'UTILIZAR-AQUI-O-TOKEN-DO-BOT-DO-DISCORD-GERADO-ACIMA'

intents = discord.Intents.default()
intents.guilds = True
intents.messages = True
client = discord.Client(intents=intents)

@client.event

async def main():
    async with client:
        await client.start(TOKEN)

if __name__ == '__main__':
    asyncio.run(main())
```

O código acima define um cliente com permissões básicas (`intents`) para acessar guildas (grupos / servidores) e mensagens no Discord. A função `main()` é responsável por iniciar o bot de forma assíncrona, conectando-o ao servidor do Discord com o token fornecido. Ao executar o código, o bot é iniciado, entrando nos servidores para interagir com eles de acordo com as permissões configuradas.

Execute o código abaixo para deixar o bot online

```python
python bot.py
```

E com isso, podemos ver que em nosso grupo do discord onde o bot foi instalado, agora ele está na lista de usuários online.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1724559248237/3a6adb83-e99d-4f9a-a4f2-0b42a514c9f5.png align="left")

# Obter o valor do site e postar no canal do discord

Primeiro de tudo vamos usar um site feito para testes de extração de dados, chamado [toscrape.com](http://toscrape.com), onde iremos utilizar a página do livro  
**1,000 Places to See Before You Die**  
[https://books.toscrape.com/catalogue/1000-places-to-see-before-you-die\_1/index.html](https://books.toscrape.com/catalogue/1000-places-to-see-before-you-die_1/index.html)

Para extrair o valor do livro da página acima, vamos adicionar mais alguns blocos de código em nosso `bot.py` utilizando principalmente a biblioteca **BeautifulSoup** do python.  
[https://www.crummy.com/software/BeautifulSoup/bs4/doc/](https://www.crummy.com/software/BeautifulSoup/bs4/doc/)

Farendo uma request para o site carregando o html bruto e na sequencia utilizar o `html.parser` para transforma esse HTML em uma árvore de elementos que pode ser navegada e pesquisada de forma simples.

Inspecionando o html do site, podemos ver que o preço do livro fica dentro de uma tag html onde a classe é a `price_color`

```xml
<p class="price_color">£26.08</p>
```

Com isso isso basta procurar o elemento html onde a classe seja igual a `price_color` *e utilizamos o* `.get_text()` *para obter o texto.*

Colocaremos também um intervalo para buscar novamente o preço do livro a cada 30 segundos e postamos o preço obtido do site e o horário extraído no canal **book** em todos os grupos do discord que possuem o bot instalado, com isso temos o código completo do nosso script abaixo

```python
import discord
import requests
from bs4 import BeautifulSoup
import asyncio
from datetime import datetime
import pytz

TOKEN = 'UTILIZAR-AQUI-O-TOKEN-DO-BOT-DO-DISCORD-GERADO-ACIMA'
BASE_URL = 'https://books.toscrape.com/catalogue/1000-places-to-see-before-you-die_1/index.html'
DISCORD_CHANNEL = 'book'
CHECK_INTERVAL = 30
REQUEST_TIMEOUT = 10

intents = discord.Intents.default()
intents.guilds = True
intents.messages = True
client = discord.Client(intents=intents)

async def send_status_update(guild, message, channel_name=DISCORD_CHANNEL):
    channel = discord.utils.get(guild.text_channels, name=channel_name)
    if channel:
        await channel.send(message)

def get_price():
    try:
        response = requests.get(BASE_URL, timeout=REQUEST_TIMEOUT)
        response.raise_for_status()
        soup = BeautifulSoup(response.content, 'html.parser')

        return soup.find(class_='price_color').get_text()
    except requests.RequestException as e:
        return None

async def check_status():
    await client.wait_until_ready()

    while not client.is_closed():
        price = get_price()

        if price is not None:
            time = datetime.now(pytz.timezone('America/Sao_Paulo')).strftime('%d/%m/%Y %H:%M:%S')

            for guild in client.guilds:
                await send_status_update(guild, f"{price} - {time}")

        await asyncio.sleep(CHECK_INTERVAL)

@client.event
async def on_ready():
    client.loop.create_task(check_status())

async def main():
    async with client:
        await client.start(TOKEN)

if __name__ == '__main__':
    asyncio.run(main())
```

Como modificamos o código, precisamos parar o bot que estava rodando e rodar novamente, com isso temos agora a cada 30 segundos o valor do livro extraído do site e postado em nosso canal **book**.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1724561982340/f3950a67-317b-4760-b774-4c0180c3a610.png align="center")

Como nossa base foi feita em cima de um site estático, veremos sempre o mesmo valor postado, mas como base de estudo queria deixar um exemplo funcional para todos. Mas você pode usar isso para inúmeros projetos e enviar por exemplo somente quando o valor extraído mudar, basta utilizar a imaginação agora =)

O post acabou demorando mais tempo do que a criação do script hehe, mas a idéia era compartilhar um pouco do contexto, a forma e os passos de como tudo isso foi criado.

Espero que gostem.
