Files
TextNLPClassifierApp/specs/003-article-content-extractor/research.md
T
andreferraro 6a45368cb0 feat(extractor): implement multi-engine article content extractor
- Added scripts/extract_article_contents.py for batch scraping with stealth Foxcape and triple extraction (Trafilatura, Newspaper4k, Readability)
- Created unit, integration, and E2E test suite in tests/test_extract_article_contents.py (90/90 passing)
- Updated specs/003-article-content-extractor and README.md with usage documentation and CLI contracts
- Passed ruff linting/formatting and mypy type checking cleanly
2026-08-20 19:22:20 -03:00

51 lines
4.1 KiB
Markdown

# Research: Article Content Multi-Engine Extractor
## 1. Technical Decisions & Tradeoffs
### Decision 1: Motor de Navegação e Renderização com `foxcape` em Sessão Única
- **Decision**: Utilizar `foxcape` com `FoxcapeConfig(headless=True, humanize=False)` reutilizando uma única instância de navegador através de context manager (`with Foxcape(...) as scraper:`) para todo o lote.
- **Rationale**:
- Abrir e fechar o navegador (Camoufox) para cada URL aumentaria o tempo total de processamento em 3 a 5 segundos por artigo.
- Reutilizar a sessão mantém a conexão quente, acelera o carregamento do DOM (`wait_until="domcontentloaded"`) e reduz significativamente o consumo de CPU/RAM.
- O modo stealth e as evasões de fingerprinting do Foxcape contornam bloqueios Cloudflare, TLS e proteções comuns em portais de notícias.
- **Alternatives Considered**:
- `requests` / `httpx`: Muito rápidos, porém não executam JavaScript nem resolvem páginas que necessitam de renderização DOM dinâmica (SPAs).
- `playwright` padrão: Suscetível a detecção anti-bot e requer configuração manual de stealth plugins.
---
### Decision 2: Orquestração Tripla de Extração de Conteúdo (NLP & Web Scraping)
- **Decision**: Executar 3 motores de extração complementares e consolidados:
1. **Trafilatura**: Padrão ouro em extração de texto limpo, metadados editoriais (`author`, `date`, `categories`, `tags`, `canonical_url`) e estrutura JSON nativa.
2. **Newspaper4k**: Processamento avançado de artigo (`Article`), extração de autores, data de publicação, imagens (`top_image`, `images`), e processamento NLP nativo (`nlp()`) gerando resumo automático e *keywords* no idioma do artigo.
3. **Readability (`readability-lxml`)**: Heurística clássica de legibilidade (Arc90) para isolar o nó HTML principal sem anúncios ou elementos supérfluos, além de extrair título limpo.
- **Rationale**: Cada motor possui pontos fortes distintos. A combinação dos três em uma única passagem oferece a visão mais rica e confiável possível sobre o artigo.
- **Alternatives Considered**:
- Usar apenas um dos extratores: Perderia a complementaridade (ex.: Trafilatura tem melhor parsing de texto, mas Newspaper4k oferece NLP de keywords/resumo, e Readability oferece o HTML limpo do corpo).
---
### Decision 3: Resiliência e Isolamento de Falhas por Camada
- **Decision**: Implementar try/catch defensivo em 2 níveis:
1. **Nível de Rede/Navegador**: Se o Foxcape falhar em carregar uma URL (timeout, erro 404, bloqueio), registra `extraction_status: "failed"` com a mensagem de erro e avança para a próxima URL.
2. **Nível de Extrator**: Cada extrator (`trafilatura`, `newspaper4k`, `readability`) roda em bloco isolado. Se um falhar, os outros dois concluem normalmente e o campo do extrator com falha registra `{"error": "<motivo>"}`.
- **Rationale**: Garante taxa de sucesso máxima para lotes grandes sem interrupção abrupta do processamento.
---
### Decision 4: Herança Inteligente de Idioma para NLP
- **Decision**: O Newspaper4k recebe o idioma informado no cabeçalho do JSON de busca (`"language": "es"`, `"pt"`, etc.), com fallback padrão para `"en"`, e permite sobrescrita pelo usuário via linha de comando (`-l, --language`).
- **Rationale**: As rotinas de NLP do Newspaper4k (extração de palavras-chave e resumo) dependem de dicionários e stopwords específicos do idioma.
---
### Decision 5: Gerenciamento de Memória e Descarte do Raw HTML
- **Decision**: Descartar a string HTML bruta da memória após a passagem pelos 3 extratores, persistindo no JSON final somente as entidades limpas e estruturadas.
- **Rationale**: O HTML bruto de 50 artigos pode ocupar mais de 50MB, tornando o JSON volumoso e lento para análise downstream.
---
### Decision 6: Segregação de Streams e Feedback Visual em `stderr`
- **Decision**: Emitir logs informativos e de progresso item a item (com numeração `[1/50]`, status e tempos) exclusivamente para `sys.stderr`, mantendo o `sys.stdout` intacto.
- **Rationale**: Permite acompanhar a execução no terminal em tempo real sem comprometer a interoperabilidade com pipes UNIX (`jq`, redirecionamentos).