- 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
4.1 KiB
4.1 KiB
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
foxcapecomFoxcapeConfig(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).playwrightpadrã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:
- Trafilatura: Padrão ouro em extração de texto limpo, metadados editoriais (
author,date,categories,tags,canonical_url) e estrutura JSON nativa. - 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. - 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.
- Trafilatura: Padrão ouro em extração de texto limpo, metadados editoriais (
- 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:
- 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. - 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>"}.
- Nível de Rede/Navegador: Se o Foxcape falhar em carregar uma URL (timeout, erro 404, bloqueio), registra
- 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 parasys.stderr, mantendo osys.stdoutintacto. - Rationale: Permite acompanhar a execução no terminal em tempo real sem comprometer a interoperabilidade com pipes UNIX (
jq, redirecionamentos).