# Feature Specification: Google News Headlines Extractor **Feature Branch**: `002-google-news-extractor` **Created**: 2026-08-20 **Status**: Implemented & Validated **Input**: User description: "Extrator de manchetes do Google News de acordo com assunto, idioma, locale, com Foxcape headless, resolução de URLs reais e logging" --- ## Clarifications ### Session 2026-08-20 - Q: Como o extrator de notícias do Google News deve ser disponibilizado e consumido dentro do projeto? → A: Apenas Script CLI autônomo para execução direta via linha de comando no terminal (`scripts/extract_google_news.py`). - Q: Qual biblioteca/mecanismo de requisição e raspagem deve ser utilizado no script CLI? → A: Biblioteca `foxcape` (https://pypi.org/project/foxcape/) em modo `headless=True` com proteção anti-bot e fingerprinting stealth. - Q: Como lidar com as URLs intermediárias do Google News? → A: Resolução e decodificação automática das URLs intermediárias (`https://news.google.com/rss/articles/...`) para as URLs reais e finais dos portais de notícias via `googlenewsdecoder`. - Q: Como acompanhar o progresso de extração no terminal? → A: Logs informativos em tempo real enviados exclusivamente para `sys.stderr`, mantendo `sys.stdout` limpo para pipes JSON e suportando a flag `-s / --silent`. --- ## User Scenarios & Testing *(mandatory)* ### User Story 1 - Extração Básica de Notícias com URLs Finais Resolvidas (Priority: P1) 🌟 MVP Como analista ou operador no terminal, quero fornecer um termo de busca e um idioma de interesse via linha de comando para obter rapidamente uma lista estruturada de manchetes recentes com as URLs finais reais dos veículos de imprensa (ex: *Olé, TyC Sports, ge, ESPN*). **Why this priority**: É o valor fundamental do produto. Sem a capacidade de buscar, obter manchetes e fornecer os links diretos dos veículos, o extrator não cumpre sua função de pesquisa e ingestão. **Independent Test**: Executar `python scripts/extract_google_news.py -q "River Plate" -l es --locale AR -p 1` e verificar se o JSON retornado contém notícias com URLs apontando para os domínios finais (`tycsports.com`, `ole.com.ar`, etc.). **Acceptance Scenarios**: 1. **Given** um termo de busca válido e idioma, **When** o script for executado com o motor `foxcape` em modo headless, **Then** o sistema extrai o feed RSS e decodifica as URLs de cada artigo para os sites de origem. 2. **Given** um termo de busca sem notícias correspondentes, **When** o script for executado, **Then** o sistema retorna uma coleção vazia com código de saída 0. --- ### User Story 2 - Filtragem Regional e Edição Geográfica (Priority: P2) Como usuário que monitora notícias em mercados específicos, quero definir a região/país geográfica (*locale*) além do idioma (por exemplo, espanhol da Argentina `--locale AR` vs. México `--locale MX`, ou inglês do Reino Unido `--locale GB` vs. Estados Unidos `--locale US`) para receber manchetes contextualmente relevantes àquele território. **Why this priority**: Garante relevância e precisão geográfica para análises de mídia multinacionais e segmentadas. **Independent Test**: Executar o script com idioma "es" e locale "AR" e verificar que portais e manchetes são da Argentina. **Acceptance Scenarios**: 1. **Given** um termo de busca, idioma "es" e país/região "AR", **When** o script CLI for executado, **Then** as manchetes retornadas priorizam a edição e veículos argentinos. 2. **Given** um idioma informado sem país explícito (ex: "pt"), **When** o script for solicitado, **Then** o sistema aplica o mapeamento padrão correspondente (ex: Brasil / pt-BR). --- ### User Story 3 - Paginação, Exportação em Arquivo e Feedback Visual (Priority: P3) Como operador de automação de dados, quero parametrizar o número de páginas de resultados (`--max-pages 1..10`), exportar direto para arquivo (`--output`) e acompanhar o progresso no terminal com mensagens descritivas de log. **Why this priority**: Permite flexibilidade de uso em rotinas batch, pipelines de ETL e depuração interativa. **Independent Test**: Executar com `-p 2 -o out/resultado.json` e verificar criação do arquivo com diretórios pais automáticos e logs em `stderr`. **Acceptance Scenarios**: 1. **Given** uma execução CLI com `-p 2 -o out/teste.json`, **When** o processo é executado, **Then** o terminal exibe logs em `stderr` (`[INFO] 🔍 Consultando...`, `[INFO] 🔗 Decodificando...`, `[INFO] 💾 Arquivo salvo...`) e grava o JSON final com 20 itens. 2. **Given** o uso da flag `-s` ou `--silent`, **When** o script é executado, **Then** os logs em `stderr` são suprimidos. --- ## Edge Cases - **Termo de busca vazio ou composto apenas por espaços**: O script rejeita a solicitação com mensagem de erro em `stderr` e código de saída 1. - **Falha de conectividade ou bloqueio**: O Foxcape executa com evasões anti-bot em modo headless, com captura de exceções e emissão de erro em `stderr` com código de saída 2. - **Resumo da notícia idêntico ao título**: Subtítulo redundante vira `None`. - **Caminho de saída em pasta inexistente**: O script cria os diretórios pais automaticamente antes de salvar. - **Falha na decodificação de URL específica**: Mantém a URL original como fallback gracioso sem abortar a execução dos demais itens. --- ## Requirements *(mandatory)* ### Functional Requirements - **FR-001**: O sistema DEVE ser disponibilizado como script CLI autônomo em `scripts/extract_google_news.py`. - **FR-002**: O script DEVE utilizar a biblioteca `foxcape` com `FoxcapeConfig(headless=True)` como motor primário de requisição com proteção anti-bot. - **FR-003**: O CLI DEVE aceitar argumento obrigatório para o termo de busca (`-q, --query, --keyword`). - **FR-004**: O CLI DEVE suportar argumentos opcionais para código de idioma (`-l, --lang, --language`, padrão `pt`) e região/país (`--locale, --country`). - **FR-005**: O sistema DEVE aplicar mapeamento padrão de região quando apenas o idioma for informado (`pt` → BR, `es` → AR, `en` → US, `de` → DE, `fr` → FR, `it` → IT). - **FR-006**: O CLI DEVE permitir configurar a paginação lógica (`-p, --max-pages`, de 1 a 10 páginas / 10 a 100 itens). - **FR-007**: O sistema DEVE extrair: título, URL, data de publicação, subtítulo higienizado de HTML e número da página. - **FR-008**: O sistema DEVE resolver e decodificar automaticamente as URLs intermediárias do Google News para as URLs finais dos portais de notícias em paralelo. - **FR-009**: O CLI DEVE emitir logs informativos de progresso em `sys.stderr` e suportar a flag `-s, --silent` para supressão. - **FR-010**: O CLI DEVE suportar a flag `--no-resolve-urls` para obter as URLs brutas do feed RSS quando desejado. - **FR-011**: O CLI DEVE suportar gravação em arquivo via `-o, --output` com criação de diretórios pais e formatação legível com `--pretty`. --- ## Success Criteria *(mandatory)* - **SC-001**: Extração executada com sucesso utilizando Foxcape headless e alta taxa de entrega. - **SC-002**: 100% das URLs de notícias decodificadas para os portais reais dos veículos quando a resolução de URLs estiver ativa. - **SC-003**: 100% dos resumos/subtítulos livres de marcações HTML. - **SC-004**: Formato JSON no `stdout` 100% compatível com utilitários como `jq` e pipelines shell. - **SC-005**: 100% dos testes unitários e E2E aprovados no pytest.