Pipeline Serverless e Automatizado de Captura de Ratings de Crédito Brasileiros
O Pulse Ratings Brasil é um pipeline de ETL (Extração, Transformação e Carga) serverless projetado para coletar, tratar e disponibilizar dados de ratings de crédito (corporativos e soberanos) das principais agências de classificação de risco em atuação no Brasil: S&P, Moody's, Fitch, Austin Rating e Liberum Ratings.
Ele funciona 100% de forma automatizada via GitHub Actions, salvando o histórico consolidado diretamente no repositório em formato CSV plano. Os dados tratados alimentam um dashboard interativo servido via GitHub Pages.
- Arquitetura Baseada em OOP: Scrapers estruturados sob uma classe base infraestrutural (
BaseScraper) que gerencia nativamente o ciclo de vida, sanitização de tipos e geração de logs. - Deduplicação Inteligente: A persistência em CSV mescla dados novos com antigos no mesmo dia, substituindo re-execuções sem duplicar linhas e mantendo o histórico intacto.
- Detecção de Schema Drift: Alertas automáticos caso as colunas das tabelas originais fornecidas pelas agências mudem de layout.
- Catálogo Dinâmico: Geração automatizada do catálogo de dados (
datasets.json) e mapeamento de tipos de campos (schemas.json) a cada execução do pipeline. - Dashboard Vanilla CSS/JS: Uma interface web rápida e responsiva para buscar, filtrar por agência e baixar os arquivos CSV sem sobrecarga de frameworks pesados.
graph TD
A[GitHub Actions Cron / Trigger] --> B[run_all.py Orchestrator]
B -->|Dynamic Discovery| C["scrapers/ folder"]
B -->|Executes Phase 1| D["Independent Scrapers: Entities (Moody's, S&P, Fitch, Austin, Liberum)"]
B -->|Executes Phase 2| E["Dependent Scrapers: Ratings (Moody's, S&P, Fitch, Austin, Liberum)"]
D --> F["data/*.csv files"]
E --> F
F --> G["scripts/consolidar_emissores.py"]
G --> H["data/emissores_consolidado.csv"]
F & H --> S["scripts/separar_emissores_emissoes.py"]
S --> RE["data/ratings_emissores.csv"]
S --> RM["data/ratings_emissoes.csv"]
RE & RM & H --> I["data/datasets.json (generate_catalog.py)"]
I --> J[git push origin main]
J --> K[GitHub Pages / index.html]
PulseRatingsBrasil/
├── .github/
│ └── workflows/
│ └── main.yml # Agendamento do pipeline no GitHub Actions
├── databricks/ # Integração nativa Databricks (Git Folders & Workflows)
│ ├── notebooks/
│ │ ├── 01_orchestrator_notebook.py # Notebook interativo com widgets para depuração
│ │ └── 02_delta_lake_exporter.py # Exportador de CSVs para tabelas Delta Lake
│ ├── run_pulse_ratings_brasil_job.py # Entrypoint Python Script para Databricks Workflows
│ ├── delta_exporter.py # Utilitário de carga e conversão para Delta Lake
│ ├── init.sh # Init script para instalação de libs nativas (curl-cffi)
│ ├── requirements.txt # Dependências otimizadas para runtime Databricks
│ └── README.md # Guia passo a passo de configuração e agendamento
├── data/ # Datasets, schemas e metadados de controle
│ ├── datasets.json # Catálogo estruturado de metadados dos datasets
│ ├── schemas.json # Definição e mapeamento de campos e tipos
│ ├── pipeline_status.json / .js # Logs de saúde e duração da última execução
│ ├── last_updates.json / .js # Período de cobertura temporal de cada CSV
│ ├── emissores_consolidado.csv # Emissores consolidados (1 linha por emissor + CNPJ)
│ ├── ratings_emissores.csv # Ratings corporativos de nível de emissor/entidade consolidados
│ ├── ratings_emissoes.csv # Ratings de instrumentos (debentures, FIDCs, CRIs/CRAs) consolidados
│ └── *.csv # Séries temporais de ratings de crédito
├── tests/ # Testes automatizados
│ ├── __init__.py
│ └── test_consolidar_emissores.py # Testes do script de consolidação
├── scrapers/ # Módulos de captura
│ ├── utils/
│ │ ├── __init__.py
│ │ └── base.py # Classe base BaseScraper
│ └── *.py # Scripts de coleta (duplas emissores/ratings por fonte)
├── utils/ # Utilitários compartilhados auxiliares
│ ├── __init__.py
│ ├── base.py # Salvamento de CSVs e helpers HTTP
│ └── parsers.py # Parsers auxiliares para formatos especiais
├── scripts/ # Scripts de ciclo de vida
│ ├── consolidar_emissores.py # Consolida emissores das agências em 1 CSV
│ ├── separar_emissores_emissoes.py # Separa e normaliza ratings de emissores e emissões
│ ├── generate_catalog.py # Gerador automatizado do catálogo de datasets
│ ├── gerar_consulta_json.py # Gera JSON otimizado para o dashboard de consulta
│ ├── preencher_cnpj_cvm.py # Preenche CNPJ via dados offline da CVM
│ ├── preencher_cnpj_api.py # Preenche CNPJ via CNPJ Aberto API (1.000 req/dia)
│ ├── preencher_cnpj_rfb.py # Preenche CNPJ via base local da Receita Federal
│ └── utils/
│ ├── __init__.py
│ └── ux.py # Utilitários de UX (cores, ícones, progresso)
├── run_all.py # Orquestrador CLI central do projeto
├── requirements.txt # Dependências do Python
├── .env.example # Template de variáveis de ambiente
├── index.html # Dashboard estático do projeto
└── README.md
O Pulse Ratings Brasil possui suporte nativo para execução no Databricks, permitindo orquestrar os scrapers via Databricks Workflows (Jobs UI), depurar interativamente através de Notebooks com Widgets e exportar os dados consolidados diretamente para tabelas Delta Lake no Hive Metastore ou Unity Catalog.
- Git Folders (Repos) Padrão: Conecte o repositório diretamente pela UI do Databricks (
Workspace > Users > Git folder), sem necessidade de Databricks Asset Bundles (DABs) ou permissões administrativas especiais. - Entrypoint Python Script Task: O script
databricks/run_pulse_ratings_brasil_job.pyresolve dinamicamente osys.path, recupera credenciais do Databricks Secret Scope (ou variáveis de ambiente) e executa o pipeline sem duplicar lógica de código. - Notebook Interativo com Widgets: O notebook
databricks/notebooks/01_orchestrator_notebook.pydisponibiliza dropdowns visuais para rodar scrapers específicos, filtrar por grupos (ratings,emissores), alternar execução paralela/sequencial e depurar em tempo real. - Exportador Delta Lake: O notebook
databricks/notebooks/02_delta_lake_exporter.pyconverte automaticamente os CSVs para tabelas Delta Lake com colunas de auditoria (_ingestion_timestamp), permitindo consultas analíticas imediatas via Databricks SQL ou conexões com Power BI.
# Execução via Python Script Task ou terminal Databricks
python databricks/run_pulse_ratings_brasil_job.py --parallel --max-workers 4
# Executar apenas um scraper específico
python databricks/run_pulse_ratings_brasil_job.py --scraper fitch_ratings
# Executar pipeline e exportar diretamente para Delta Lake
python databricks/run_pulse_ratings_brasil_job.py --export-delta📖 Guia Completo Passo a Passo: Consulte a documentação dedicada em databricks/README.md para detalhes visuais de clonagem, configuração de secrets, criação do Job agendado e consultas SQL analíticas.
-
Clone o repositório:
git clone https://github.com/PulseDataLabs/PulseRatingsBrasil.git cd PulseRatingsBrasil -
Configure o ambiente virtual e instale as dependências:
O
uvé um gerenciador de pacotes extremamente rápido escrito em Rust.# Cria o ambiente virtual (.venv) uv venv # Ativa o ambiente virtual source .venv/bin/activate # Instala as dependências uv pip install -r requirements.txt
Caso prefira a abordagem clássica do Python:
# Cria o ambiente virtual (venv) python -m venv venv # Ativa o ambiente virtual source venv/bin/activate # Instala as dependências pip install -r requirements.txt
-
Configure o arquivo de variáveis de ambiente:
cp .env.example .env
(Edite o
.envcaso queira evitar o fallback dinâmico de APIs ou configurar a persistência de dados no Oracle Cloud Autonomous Database).
Para habilitar a gravação automatizada dos dados no Oracle Cloud Autonomous Database, configure as seguintes variáveis no arquivo .env:
ORACLE_DB_USER: Usuário do banco de dados.ORACLE_DB_PASSWORD: Senha do usuário.ORACLE_DB_DSN: O DSN de conexão (Service Name do seu banco de dados).ORACLE_DB_WALLET_DIR: O caminho local absoluto para o diretório descompactado contendo os arquivos da Wallet (ex: contendocwallet.sso,tnsnames.ora). Se omitido ou vazio, o driver tentará conectar via One-Way TLS. Caso preenchido, usará Mutual TLS (mTLS).ORACLE_DB_WALLET_PASSWORD: A senha da Wallet (opcional).
Se as credenciais não forem fornecidas ou a variável de ambiente SKIP_ORACLE_DB estiver configurada como 1, a persistência no banco de dados será ignorada silenciosamente e sem crashar a gravação local dos arquivos CSV.
-
Executar todos os scrapers ativos:
python run_all.py
-
Executar ignorando a persistência no banco de dados Oracle:
python run_all.py --skip-db
-
Executar sequencialmente (ideal para depuração):
python run_all.py --sequential
-
Executar apenas um scraper específico:
python run_all.py --scraper moodys_ratings
-
Regenerar apenas o catálogo
datasets.json:python run_all.py --generate-catalog
O campo cnpj_emissor do consolidado é preenchido por 3 scripts, executados em ordem:
| Script | Fonte | Onde roda | Limitação |
|---|---|---|---|
preencher_cnpj_cvm.py |
CVM (cias abertas + fundos) | GitHub Actions (automático) | ~400-500 matches |
preencher_cnpj_api.py |
CNPJ Aberto API | GitHub Actions (automático) | 1.000 req/dia free |
preencher_cnpj_api_proxy.py |
Idem + proxy automático | Local (quando API bate rate limit) | Depende dos proxies públicos |
preencher_cnpj_rfb.py |
Receita Federal (base completa) | Local apenas | ~1.4GB download |
RFB (local — download automático via WebDAV):
# Executar (baixa Empresas*.zip do mês mais recente automaticamente):
python scripts/preencher_cnpj_rfb.py
# Para recriar o banco SQLite do zero (útil para atualizar a base):
python scripts/preencher_cnpj_rfb.py --rebuild-dbO script descobre o mês mais recente via WebDAV no repositório oficial da
Receita Federal, baixa os 10 arquivos Empresas0.zip..Empresas9.zip
(~1.4GB total), extrai as empresas para um banco SQLite local com índice
de nomes normalizados, e busca cada emissor pendente por nome exato ou
fallback por palavras significativas.
Proxy automático (quando a API bater rate limit):
python scripts/preencher_cnpj_api_proxy.pyRaspa proxies gratuitos de 4 fontes públicas, valida o primeiro
funcionando contra httpbin.org, e delega o preenchimento à API
com o proxy setado automaticamente via CNPJABERTO_PROXY.
O orquestrador run_all.py organiza os scrapers em grupos. Este repositório contém scrapers de múltiplos domínios:
| Grupo | Descrição | Scrapers |
|---|---|---|
ratings |
Ratings de crédito (S&P, Moody's, Fitch, Austin, Liberum) | standard_and_poors_ratings, standard_and_poors_emissores, moodys_ratings, moodys_emissores, fitch_ratings, fitch_emissores, austin_ratings, austin_emissores, liberum_ratings, liberum_emissores |
consolidated |
Emissores consolidados (1 linha por emissor) | emissores_consolidado |
anbima |
Dados ANBIMA | (implementação externa) |
b3 |
Dados B3 | (implementação externa) |
bcb |
Dados Banco Central | (implementação externa) |
cvm |
Dados CVM | (implementação externa) |
ibge |
Dados IBGE | (implementação externa) |
misc |
Outras fontes | (implementação externa) |
Apenas o grupo ratings está ativo por padrão neste repositório público.
- Tipo: Scraper web com extração dinâmica de chave pública
- Autenticação: Opcional (
SP_GLOBAL_API_KEY). Sem a chave, o scraper extrai a chave pública dinamicamente. - Dados coletados: Ratings de emissor e lista de emissores
- Frequência: Cada execução do pipeline
- Tipo: Planilhas Excel (.xlsx) e dados estruturados
- Autenticação: Pública (sem chave)
- Dados coletados: Ratings de emissor e lista de emissores
- Frequência: Cada execução do pipeline
- Tipo: API GraphQL pública
- Autenticação: Pública (sem chave)
- Dados coletados: Ratings de emissor e lista de emissores
- Frequência: Cada execução do pipeline
- Tipo: Web scraper concorrente baseado em requisições HTTP e tabelas HTML
- Autenticação: Pública (sem chave)
- Dados coletados: Ratings de emissor e lista de emissores
- Frequência: Cada execução do pipeline
- Tipo: Consumo direto da API pública de listagem do painel em React
- Autenticação: Pública (sem chave para listagem de ratings ativos / arrays internos)
- Dados coletados: Ratings por classe/escala e lista de emissores
- Frequência: Cada execução do pipeline
Cada arquivo CSV segue o padrão: UTF-8, separador vírgula, decimal ponto, datas YYYY-MM-DD.
Os campos comuns a todos os datasets:
| Campo | Tipo | Descrição |
|---|---|---|
dt_captura |
date | Data da captura pelo pipeline |
no_emissor |
str | Nome do emissor |
O dataset emissores_consolidado.csv possui estrutura própria:
| Campo | Tipo | Descrição |
|---|---|---|
no_emissor_padronizado |
str | Nome normalizado (uppercase, sem acentos, sem sufixos) |
no_emissor_fitch |
str | Nome original na fonte Fitch |
no_emissor_moodys |
str | Nome original na fonte Moody's |
no_emissor_standard_and_poors |
str | Nome original na fonte S&P |
no_emissor_austin |
str | Nome original na fonte Austin Rating |
no_emissor_liberum |
str | Nome original na fonte Liberum Ratings |
cnpj_emissor |
str | CNPJ do emissor (preenchido via CVM + CNPJ Aberto API + base RFB) |
As definições completas de campos e tipos são geradas automaticamente em data/schemas.json a cada execução e exibidas no dashboard.
- Faça um fork do repositório
- Crie uma branch para sua feature:
git checkout -b minha-feature - Faça o commit das alterações:
git commit -m "feat: descrição concisa" - Envie para o remote:
git push origin minha-feature - Abra um Pull Request
- Commits seguem Conventional Commits
- Código Python segue PEP 8
- Docstrings no formato Google style
| Problema | Causa | Solução |
|---|---|---|
| S&P retorna dados vazios | Chave pública expirada ou bloqueada | Executar novamente — o scraper tenta extrair nova chave automaticamente |
| Schema drift alerta | Agência modificou colunas do layout | Revisar o drift em pipeline_status.json e atualizar se necessário |
| Pipeline timeout no GH Actions | Execução excede 6h | Verificar scraper específico com --sequential localmente |
Erro xlrd.biffh.XLRDError |
Arquivo Excel no formato .xlsx |
O fallback para openpyxl é automático |
- Padronização do campo de captura para
dt_captura - Dashboard com busca, filtros e schema dinâmico
- Suporte a 10 datasets de ratings (5 agências × ratings + emissores)
- Integração da Austin Rating e da Liberum Ratings (incluindo tratamento de timeouts e retries na API)
- Detecção automática de schema drift
- Consolidação de emissores: script + testes + dataset
emissores_consolidado.csvcom suporte a 5 agências - Sistema de UX unificado (cores, progresso, logging) nos scrapers e orquestrador
- Pipeline inicial com scrapers S&P, Moody's e Fitch
- Schema drift detection
- Catálogo dinâmico de datasets
Para reportar vulnerabilidades, abra uma issue com o label security ou entre em contato pelo GitHub.
Este projeto está sob a licença MIT. Consulte o arquivo LICENSE para obter mais detalhes.
Desenvolvido com 💙 por PulseDataLabs.
Dados públicos de rating — S&P, Moody's, Fitch, Austin e Liberum