Obtendo os dados da B3 utilizando Python e frameworks de RPA

Surgiu uma necessidade de baixar os dados disponibilizados no site da B3 através do download de arquivos referente ao tópico “Banco de Dados Completo”, através do link Código ISIN | B3, conforme imagem abaixo.

Caminho de onde os arquivos são baixados no site da B3:

Esse link ele extrai os dados de um arquivos com a extensão .zip, e dentro desse arquivo zipado possui três arquivos: EMISSOR.TXT, NUMERACA.TXT e Leiame.pdf.

Portanto ao invés do usuário entrar no site diariamente (ou no período que ele preferir) e baixar esses dados, criei um script em Python com estruturas de de RPA utilizando principalmente a biblioteca selenium.

A biblioteca selenium ela literalmente abre o navegador desejado (no script utilizamos o Google Chrome) e pega as informações já renderizadas dentro do próprio navegador, ou seja, o script abre o link informado e clica no ícone que expande o menu e clica no botão “Banco de Dados Completo” para fazer o download dos arquivos necessários. Para chegar nesse caminho, eu inspecionei o objeto dentro do navegador e copiei o caminho XPath, conforme demonstrado na imagem abaixo.

Obter o caminho XPath do objeto dentro do site

Apesar de ser o meu primeiro script em Python profissional e não acadêmico, com certeza deve haver muitas melhorias a serem feitas, porém, conseguiu solucionar o problema desejado.

Portanto, para essa solução, o script faz as seguintes etapas:

1.1. Importa as bibliotecas necessárias
1.2. Define os diretórios onde será baixado os arquivos e posteriormente copiados
1.3. Verifica se já possui arquivo com a extensão .zip ou .txt no diretório de origem, caso tenha, ele deleta os arquivos

2.1. Define a URL que o selenium deverá abrir
2.2. Define onde está o driver do navegador escolhido
2.3. Abre o navegador e faz os comandos necessários automaticamente

3.1. Verifica se possui arquivo com a extensão .zip baixada e cria um dataframe dos arquivos que estão dentro do arquivo compactado
3.2. Extrai os arquivos somente com a extensão .txt, que serão utilizados num futuro data stage
3.3. Renomeia os arquivos
3.4. Copia os arquivos para um diretório de destino

Como exemplo, os arquivos que estão dentro do arquivo compactado atualmente são:

Arquivos dentro do arquivo compactado

Lembrando que para o script funcionar corretamente, é necessário fazer o download do driver do Google de acordo com a versão do seu navegador. Abaixo segue o script completoem Python:

# Importa os módulos necessários para o script ser executado
import pandas as pd
import time
import datetime
import shutil
import os
import glob
import zipfile
import pathlib
import plotly.figure_factory as ff

from selenium import webdriver

# Define o nome do diretório onde está o arquivo baixado
src = pathlib.Path("D:\\Users\\F02579\\Downloads")

# Define o diretório aonde o arquivo será copiado após baixado
dst = pathlib.Path("D:\\Users\\F02579\\Documents")

# Recebe os arquivos do diretório na variavel
files = os.listdir(src)

# Verifica se possui algum arquivo com a extensão ZIP e TXT no diretório, e se estiver, deleta o arquivo
for file in files:
if file.lower().endswith(('.zip', '.txt')):
print(os.path.join(src, file))
os.remove(os.path.join(src, file))

# A URL abaixo foi retirado do link do site
# http://www.b3.com.br/pt_br/market-data-e-indices/servicos-de-dados/market-data/consultas/mercado-a-vista/codigo-isin/pesquisa/

# Coloque a URL abaixo
url = "https://sistemaswebb3-listados.b3.com.br/isinPage/#accordionBodyTwo"

# Para abrir o Chrome automaticamente, deve baixar o driver chromedriver de acordo com a versão da web instalado
options = webdriver.ChromeOptions()
options.add_argument('--allow-running-insecure-content')
options.add_argument('--allow-running-localhost')
options.add_argument('--ignore-certificate-errors')
options.add_argument('--ignore-ssl-errors')
executable_path = "C:\Program Files (x86)\Google\Chrome\Application\chromedriver.exe"

# A partir dessa etapa, ele virá fazer tudo automaticamente dentro do browser
# Abre o browser do Google Chrome automaticamente
browser = webdriver.Chrome(executable_path, options = options)

# Obtém os dados através da variavel URL
browser.get(url)

# Aguarda 10 segundos, para o link do site ser carregado antes de ser clicado automaticamente
time.sleep(10)

# Através do browser, ele clica no sinal de expandir o quadrante onde se encontra o item a ser clicavel
browser.find_element_by_xpath('//*[@id="accordionHeadingTwo"]/div/div/a').click()

# Aguarda 10 segundos, para o link do site ser carregado antes de ser clicado automaticamente
time.sleep(10)

# Através do browser ele clica no item que faz o download dos arquivos necessários. Através do titulo "Banco de Dados Completo"
browser.find_element_by_xpath('//*[@id="accordionBodyTwo"]/div/div[1]/div[1]/div[2]/p[1]/a').click()

# Adiciona 1 segundo enquanto o arquivo baixado com a extensão zip não constar no diretório, antes de fechar o browser
# Após ser baixado, adiciona o nome do arquivo para uma variável
while not glob.glob(str(src) + "\*.zip"):
time.sleep(1)
else:
print("Arquivo baixado do link " + str(url))

# Fecha o browser
browser.close()

# Aguarda 5 segundos, para o arquivo ser baixado corretamente
time.sleep(5)
# Recebe os arquivos do diretório na variavel
files = os.listdir(src)
# Verifica se possui algum arquivo com a extensão zip no diretório
MetadataFiles = pd.DataFrame([])
# Verifica se possui algum arquivo com a extensão zip no diretório
for file in files:
if file.lower().endswith('.zip'):
zip = os.path.join(src, file)
print(zip)
# Caso tenha o arquivo zip, cria um data frame para vermos os dados dentro do arquivo zip
with zipfile.ZipFile(zip) as myzip:
for info in myzip.infolist():
MetadataFiles = MetadataFiles.append(pd.DataFrame({'ZipFile': [os.path.basename(zip)],'FileName': [info.filename], 'Extension': [os.path.splitext(info.filename)[1].lower()], 'Size': [str(info.file_size/1000) + ' Kb'], 'Directory': [src],'Modified': [str(datetime.datetime(*info.date_time))]}))
df = pd.DataFrame(MetadataFiles, columns = ['ZipFile','FileName','Extension','Size', 'Directory', 'Modified'])
# Mostra os data frame criado dentro do aquivo zip
print(df.head())

# Cria a tabela do plotly de acordo com o data frame criado anteriormente
fig = ff.create_table(df)

# Exibe a tabela
fig.show()

# Extrai somente os arquivos com a extensão TXT do arquivo zip na variavel do diretório de destino
QtdArq = 0
with zipfile.ZipFile(zip) as myzip:
for FileName in myzip.namelist():
if FileName.lower().endswith(".txt"):
myzip.extract(FileName, src)
QtdArq +=1

# Exibe uma mensagem que foi descompactado corretamente
print("Foram descompactados " + str(QtdArq) + " arquivos")

# Renomeia o arquivo descompactado para o nome desejado, e salva no diretório de destino da variavel dst
os.rename(pathlib.Path(str(src) + "\\EMISSOR.TXT"), pathlib.Path(str(src) + "\\I_EMISSOR.TXT"))
os.rename(pathlib.Path(str(src) + "\\NUMERACA.TXT"), pathlib.Path(str(src) + "\\I_NUMERACA.TXT"))

# Copia os arquivos extraidos o para o diretório da variavel dst
QtdArq = 0
for file in files:
if os.path.isfile(os.path.join(src, file)):
if file.lower().endswith('.txt'):
shutil.copy(os.path.join(src, file), dst)
QtdArq +=1

# Exibe uma mensagem de quantos arquivos foram copiados
print("Foram copiados " + str(QtdArq) + " arquivos para o diretório " + str(dst))
Gif do processo funcionando

Apesar do processo manual não ser tão demorado, com esse script conseguimos automatizar uma conexão com uma fonte de dados que antes dependia de um usuário para ser finalizada, e agora podemos obter automaticamente e carregar esses dados para uma tabela.

Qualquer duvida pode entrar comigo diretamente através do meu Linkedin, ou aqui nos comentários.

Guilherme Matheus | LinkedIn

Mechanical Engineer Business Intelligence developer, passionate about technology, I have knowledge and experience to create a BI architecture and much more 📚.

Mechanical Engineer Business Intelligence developer, passionate about technology, I have knowledge and experience to create a BI architecture and much more 📚.