Files
TextNLPClassifierApp/specs/002-google-news-extractor/research.md
T
andreferraro 6e3d57619b feat(extractor): add Google News headlines extractor with Foxcape headless and URL resolution
- Add standalone CLI script scripts/extract_google_news.py for Google News RSS scraping
- Integrate foxcape in headless mode as primary stealth anti-bot engine
- Implement parallel article URL resolution using googlenewsdecoder and ThreadPoolExecutor
- Support language and regional locale mapping (-l, --lang, --locale)
- Implement real-time progress logging in stderr and --silent flag
- Add unit, integration, and live E2E tests in tests/test_extract_google_news.py
- Add full SpecKit documentation (specs/002-google-news-extractor/)
- Create comprehensive README.md covering both NLP Classifier and Google News Extractor
2026-08-20 11:50:16 -03:00

48 lines
3.5 KiB
Markdown

# Research: Google News Headlines Extractor
## 1. Technical Decisions & Tradeoffs
### Decision 1: Motor de Requisição e Scraping com `foxcape` em Modo Headless
- **Decision**: Adotar o pacote `foxcape` com `FoxcapeConfig(headless=True, humanize=False)` como motor de requisição primário.
- **Rationale**: `foxcape` integra Camoufox e BeautifulSoup com evasões de fingerprinting TLS, runtime JS e headers avançados, impedindo bloqueios (429/403/Captchas) frequentes do Google News. A configuração `headless=True` garante que a execução ocorra 100% em segundo plano sem abrir janelas gráficas no sistema.
- **Alternatives Considered**:
- `curl_cffi` + `beautifulsoup4` manual: Boa alternativa, mas exige orquestração manual de impersonação de TLS e headers.
- `requests` padrão: Alto risco de bloqueio anti-bot pelo Google News.
- Foxcape padrão sem configuração (`headless=False`): Abre janela visual do Firefox indesejada em execuções CLI e servidores.
---
### Decision 2: Endpoint RSS do Google News vs. Scraping de DOM
- **Decision**: Utilizar o endpoint oficial de busca RSS do Google News: `https://news.google.com/rss/search?q={query}&hl={hl}&gl={gl}&ceid={gl}:{hl}`.
- **Rationale**: Formato estruturado em XML padrão, com carregamento rápido e direto de todos os metadados necessários (`title`, `link`, `pubDate`, `description`), sem necessidade de lidar com seletores CSS voláteis da interface web renderizada.
- **Alternatives Considered**:
- Scraping direto da interface HTML do Google News (`news.google.com/search`): Classes CSS ofuscadas e alteradas frequentemente pelo Google, quebrando facilmente a extração.
---
### Decision 3: Mapeamento de Idioma e Locale (`hl`, `gl`, `ceid`)
- **Decision**: Tabela de mapeamento determinística com fallback dinâmico.
- `pt` → `hl=pt-BR`, `gl=BR`, `ceid=BR:pt-BR`
- `es` → `hl=es-419`, `gl=AR`, `ceid=AR:es-419`
- `en` → `hl=en-US`, `gl=US`, `ceid=US:en-US`
- `de` → `hl=de`, `gl=DE`, `ceid=DE:de`
- `fr` → `hl=fr`, `gl=FR`, `ceid=FR:fr`
- `it` → `hl=it`, `gl=IT`, `ceid=IT:it`
- Customizado: se fornecido `--locale MX`, sobrescreve o `gl` e ajusta `ceid={gl}:{hl}`.
- **Rationale**: Garante notícias contextualmente adequadas por país sem que o usuário precise memorizar os códigos técnicos internos do Google News.
---
### Decision 4: Resolução de URLs do Google News via `googlenewsdecoder`
- **Decision**: Resolver automaticamente as URLs intermediárias (`news.google.com/rss/articles/CBMi...`) para os links originais dos veículos de imprensa em lote com `concurrent.futures.ThreadPoolExecutor(max_workers=5)`.
- **Rationale**: Os links gerados pelo Google News contêm tokens RPC intermediários que dificultam a leitura e ingestão direta. A decodificação em lote resolve até 50 URLs em menos de 1 segundo sem sobrecarga.
- **Alternatives Considered**:
- Resolução via Playwright headless para cada link: Muito lenta para listas de 20 a 50 notícias (demora 30 a 60 segundos).
- Manter apenas a URL do Google News: Prejudica o usuário e sistemas downstream que precisam do domínio e link real do portal de notícias.
---
### Decision 5: Logging em Tempo Real no `stderr` e Segregação de Streams
- **Decision**: Enviar mensagens de status (`[INFO] ...`) para `sys.stderr` e reservar `sys.stdout` exclusivamente para o JSON.
- **Rationale**: Permite que o operador acompanhe o progresso em tempo real no terminal (`Consultando...`, `Decodificando URLs...`, `Arquivo salvo...`) sem quebrar a interoperabilidade com ferramentas de pipe como `jq` ou redirecionamentos de arquivo.