Skip to content

feat: add active field to agency YAML configuration#4

Merged
miguellsfilho merged 5 commits intomainfrom
feat/active-field-agencies
Feb 27, 2026
Merged

feat: add active field to agency YAML configuration#4
miguellsfilho merged 5 commits intomainfrom
feat/active-field-agencies

Conversation

@miguellsfilho
Copy link
Contributor

Contexto

Este PR migra as mudanças do PR #70 do repositório data-platform para resolver a Issue #64: a impossibilidade de desabilitar agências de forma programática.

Problema Original

  • Desabilitar agências com URLs problemáticas (502, 404) exigia comentar linhas no YAML com #
  • Perda de informação sobre quando/por que foi desabilitada
  • Dificuldade de gestão programática

Solução Implementada

Converter formato YAML de string simples para dicionário com campos:

  • url: URL da página de notícias (obrigatório)
  • active: Flag booleano para ativar/desativar (opcional, default: true)
  • disabled_reason: Motivo da desativação (opcional)
  • disabled_date: Data da desativação (opcional)

Mudanças

1. Sistema active para gov.br

Arquivo Mudança
src/govbr_scraper/scrapers/config/site_urls.yaml Convertido para formato dicionário (~158 agências)
src/govbr_scraper/scrapers/scrape_manager.py Adicionados _extract_url(), _is_agency_inactive() e filtro em _load_urls_from_yaml()

2. Sistema active para EBC

Arquivo Mudança
src/govbr_scraper/scrapers/config/ebc_urls.yaml NOVO - 3 fontes (memoria-ebc inativa, agencia-brasil e tvbrasil ativas)
src/govbr_scraper/scrapers/ebc_webscraper.py Parametrizado base_url, adicionado _get_base_domain(), 3 estratégias de scraping
src/govbr_scraper/scrapers/ebc_scrape_manager.py Carregamento YAML, filtro de inativos, parâmetro agencies

3. API

Arquivo Mudança
src/govbr_scraper/api.py Parâmetro agencies no endpoint /scrape/ebc

4. Storage

Arquivo Mudança
src/govbr_scraper/storage/postgres_manager.py Deduplicação intra-batch por unique_id

5. DAGs

Arquivo Mudança
dags/config/site_urls.yaml Sincronizado com formato dicionário
dags/scrape_agencies.py _load_agencies_config() filtra agências inativas

6. Testes

Arquivo Mudança
tests/unit/test_scrape_manager.py NOVO - 13 testes para gov.br
tests/unit/test_ebc_scrape_manager.py NOVO - 15 testes para EBC
tests/unit/test_ebc_scraper.py Fixture atualizada para novo parâmetro base_url

Formato do novo YAML

site_urls.yaml (gov.br)

agencies:
  mec:
    url: https://www.gov.br/mec/pt-br/assuntos/noticias
    active: true
  cisc:
    url: https://www.gov.br/pt-br/noticias
    active: false
    disabled_reason: "URL generica - retorna noticias de todas as agencias"
    disabled_date: "2025-01-15"

ebc_urls.yaml

agencies:
  memoria-ebc:
    url: https://memoria.ebc.com.br/noticias
    active: false
    disabled_reason: "Site fora do ar (502 Bad Gateway) - issue #50"
    disabled_date: "2026-02-12"
  agencia-brasil:
    url: https://agenciabrasil.ebc.com.br/ultimas
    active: true
  tvbrasil:
    url: https://tvbrasil.ebc.com.br/ultimas
    active: true

Test Plan

  • poetry run pytest tests/unit/ -v - 35 testes passando
  • Testar endpoint /scrape/agencies com agência ativa
  • Testar endpoint /scrape/agencies com agência inativa (deve falhar)
  • Testar endpoint /scrape/ebc com agencies: ["agencia-brasil"]
  • Testar endpoint /scrape/ebc com agencies: ["memoria-ebc"] (deve falhar - inativa)
  • Verificar que DAGs são geradas apenas para agências ativas

Arquivos para Revisar (prioridade)

  1. src/govbr_scraper/scrapers/scrape_manager.py - Lógica de filtro de agências
  2. src/govbr_scraper/scrapers/ebc_scrape_manager.py - Novo sistema de carregamento YAML e múltiplas fontes
  3. src/govbr_scraper/scrapers/ebc_webscraper.py - Múltiplas estratégias de scraping (linhas 239-318)
  4. dags/scrape_agencies.py - Filtro de agências inativas nas DAGs

Riscos e Mitigações

Risco Mitigação
Breaking change no formato YAML Mantida compatibilidade dual (mas não utilizada neste PR)
Nome agency EBC mudou (agencia_brasilagencia-brasil) Apenas novos registros usam o novo nome

🤖 Generated with Claude Code

This commit migrates changes from PR #70 in data-platform repository
to resolve Issue #64: the inability to programmatically disable agencies.

## Problem
Previously, disabling agencies with problematic URLs (502, 404) required
commenting lines in YAML with `#`, causing loss of information about
when/why they were disabled and making programmatic management difficult.

## Solution
Convert YAML format from simple strings to dictionaries with fields:
- `url`: Agency news page URL (required)
- `active`: Boolean flag to enable/disable (optional, default: true)
- `disabled_reason`: Why the agency was disabled (optional)
- `disabled_date`: When it was disabled (optional)

## Changes

### Gov.br Scraper
- `site_urls.yaml`: Converted to dictionary format with ~158 agencies
- `scrape_manager.py`: Added `_extract_url()`, `_is_agency_inactive()`,
  and updated `_load_urls_from_yaml()` to filter inactive agencies

### EBC Scraper
- Created `ebc_urls.yaml` with 3 sources (memoria-ebc inactive,
  agencia-brasil and tvbrasil active)
- `ebc_webscraper.py`: Parameterized `base_url`, added `_get_base_domain()`,
  implemented 3 scraping strategies for different EBC sites
- `ebc_scrape_manager.py`: Added YAML loading, inactive filtering,
  and `agencies` parameter to `run_scraper()`

### API
- `api.py`: Added `agencies` parameter to `/scrape/ebc` endpoint

### Storage
- `postgres_manager.py`: Added intra-batch deduplication by `unique_id`
  to handle race conditions during pagination

### DAGs
- `dags/config/site_urls.yaml`: Synced with src/ version
- `dags/scrape_agencies.py`: Updated to filter inactive agencies

### Tests
- Added 35 unit tests for new functionality
- All tests passing

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Copy link
Contributor

@nitaibezerra nitaibezerra left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

PR bem estruturado, descrição excelente. Algumas observações:

1. Duplicação entre ScrapeManager e EBCScrapeManager

_extract_url(), _is_agency_inactive() e _load_urls_from_yaml() são idênticos nos dois managers. Qualquer fix futuro precisa ser feito em dois lugares. Sugestão: extrair para classe base ou módulo utilitário (pode ser follow-up).

2. agencia_brasilagencia-brasil é breaking change silenciosa

ebc_webscraper.py:418 muda o agency key de agencia_brasil para agencia-brasil. Registros novos no PostgreSQL vão ter o nome novo, antigos têm o antigo. Queries que filtram por agency (portal, analytics) vão ter inconsistência.

Opções:

  • Manter agencia_brasil (underscore) para consistência com dados existentes
  • Ou fazer um UPDATE nos registros antigos + documentar a mudança

3. agencies_processed retorna URLs em vez de nomes

Em ebc_scrape_manager.py, agencies_processed recebe scraper.base_url (ex: "https://agenciabrasil.ebc.com.br/ultimas"), mas o endpoint /scrape/agencies retorna nomes como ["mec", "mds"]. O response da API fica inconsistente entre os dois endpoints.

4. DAG tem fallback para formato legado, mas ScrapeManager não

scrape_agencies.py trata ambos os formatos (dict e string):

if isinstance(data, dict):
    active_agencies[key] = data.get("url")
else:
    active_agencies[key] = data  # formato string legado

Mas ScrapeManager._extract_url() assume sempre dict e faz agency_data["url"] direto. Se for consistente (ambos suportam ou nenhum suporta), fica mais seguro.

5. Dedup no postgres_manager — boa adição 👍

Resumo

Pontos 2 e 3 merecem atenção antes do merge. Os demais podem ser follow-up.

- Fix agencies_processed returning URLs instead of names in EBC manager
- Revert agency name from 'agencia-brasil' to 'agencia_brasil' for DB consistency
- Remove legacy string format support from DAG (only dict format now)
- Extract duplicated YAML config code to shared yaml_config.py module
- Update tests to reflect new module structure

Addresses review comments from @nitaibezerra on PR #4
@miguellsfilho
Copy link
Contributor Author

@nitaibezerra segue a implementação das correções conforme os pontos levantados.

Resumo das Alterações

Ponto 2: Breaking change agencia_brasilagencia-brasil ✅ Corrigido

Revertido para agencia_brasil (underscore) para manter consistência com dados históricos no PostgreSQL:

  • src/govbr_scraper/scrapers/ebc_webscraper.py:421 - nome da agency
  • src/govbr_scraper/scrapers/config/ebc_urls.yaml - chave do YAML

Ponto 3: agencies_processed retornando URLs ✅ Corrigido

Agora agencies_processed retorna nomes das agências (ex: ["agencia_brasil", "tvbrasil"]) em vez de URLs, mantendo consistência com o endpoint /scrape/agencies.

Arquivos modificados:

  • src/govbr_scraper/scrapers/ebc_scrape_manager.py - refatorado para usar tuplas (agency_name, scraper)

Ponto 4: Inconsistência no suporte a formato legado ✅ Corrigido

Removido suporte ao formato string legado da DAG para manter consistência (ambos agora só aceitam formato dict):

  • dags/scrape_agencies.py - removido bloco else para formato string

Ponto 1: Duplicação de código ✅ Resolvido neste PR

Extraído código duplicado para módulo compartilhado:

  • Novo arquivo: src/govbr_scraper/scrapers/yaml_config.py
    • load_urls_from_yaml() - carrega e filtra URLs do YAML
    • extract_url() - extrai URL de dados da agência
    • is_agency_inactive() - verifica se agência está inativa

Ambos managers agora importam e usam as funções do módulo compartilhado.

Arquivos Modificados

Arquivo Mudança
src/govbr_scraper/scrapers/yaml_config.py NOVO - Módulo compartilhado
src/govbr_scraper/scrapers/ebc_scrape_manager.py Usa yaml_config, corrige agencies_processed
src/govbr_scraper/scrapers/scrape_manager.py Usa yaml_config
src/govbr_scraper/scrapers/ebc_webscraper.py agencia_brasil (underscore)
src/govbr_scraper/scrapers/config/ebc_urls.yaml agencia_brasil (underscore)
dags/scrape_agencies.py Remove suporte formato legado
tests/unit/test_yaml_config.py NOVO - Testes do módulo compartilhado
tests/unit/test_ebc_scrape_manager.py Testes movidos para test_yaml_config.py
tests/unit/test_scrape_manager.py Testes movidos para test_yaml_config.py

Verificação

poetry run pytest tests/unit/ -v
# 29 passed

Contexto para Revisão com Claude

Para revisar este PR usando Claude Code, execute:

# Clonar e navegar para o branch
git fetch origin feat/active-field-agencies
git checkout feat/active-field-agencies

# Ver o diff completo desde a main
git diff main...HEAD

# Principais arquivos para revisar:
# 1. Novo módulo compartilhado
cat src/govbr_scraper/scrapers/yaml_config.py

# 2. Como os managers usam o novo módulo
git diff main...HEAD -- src/govbr_scraper/scrapers/ebc_scrape_manager.py
git diff main...HEAD -- src/govbr_scraper/scrapers/scrape_manager.py

# 3. Mudança no nome da agency
git diff main...HEAD -- src/govbr_scraper/scrapers/ebc_webscraper.py
git diff main...HEAD -- src/govbr_scraper/scrapers/config/ebc_urls.yaml

# 4. Remoção do suporte legado na DAG
git diff main...HEAD -- dags/scrape_agencies.py

Pontos de Atenção para Revisão

  1. Consistência de API: Verificar se agencies_processed agora retorna o mesmo formato em ambos endpoints
  2. Módulo compartilhado: Verificar se a extração do código duplicado foi feita corretamente
  3. Testes: Verificar se todos os casos de teste foram cobertos em test_yaml_config.py
  4. Breaking change evitada: Confirmar que agencia_brasil (underscore) está sendo usado consistentemente

- ScrapeManager now uses (agency_name, scraper) tuples like EBCScrapeManager,
  ensuring agencies_processed returns YAML keys consistently across both endpoints
- Extract get_config_dir() to yaml_config.py, removing duplication from both managers
- Delete empty test_scrape_manager.py (tests were moved to test_yaml_config.py)
- Add tests for get_config_dir()

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Contributor

@nitaibezerra nitaibezerra left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Boa, Miguel! As correções ficaram corretas — todos os 4 pontos da revisão foram endereçados adequadamente. O módulo yaml_config.py compartilhado ficou limpo, a reversão do agencia_brasil para underscore evita a breaking change, e o agencies_processed agora retorna nomes consistentemente no EBC.

Fiz algumas mudanças cosméticas no PR #5 (baseado na sua branch):

  • Unifiquei o ScrapeManager para usar o mesmo padrão de tuplas (agency_name, scraper) do EBCScrapeManager
  • Extraí o _get_config_dir() duplicado para o yaml_config.py
  • Removi o test_scrape_manager.py que ficou vazio

Pode revisar o PR #5 e, se concordar, aprovar e fazer merge dele na sua branch. Depois pode fazer merge da sua branch na main — já está aprovada por mim.

@miguellsfilho miguellsfilho merged commit a0fe91b into main Feb 27, 2026
1 check passed
@miguellsfilho miguellsfilho deleted the feat/active-field-agencies branch February 27, 2026 13:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants