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
This commit is contained in:
2026-08-20 19:22:20 -03:00
parent 6e3d57619b
commit 6a45368cb0
85 changed files with 18345 additions and 3897 deletions
+56 -6
View File
@@ -25,6 +25,10 @@
- [Diferenciais Técnicos](#diferenciais-técnicos)
- [Argumentos e Flags de Linha de Comando](#argumentos-e-flags-de-linha-de-comando)
- [Exemplos Práticos de Uso](#exemplos-práticos-de-uso)
- [3. Extrator e Parser Multimotor de Artigos](#3--extrator-e-parser-multimotor-de-artigos)
- [Visão Geral e Tríplice Extração](#visão-geral-e-tríplice-extração)
- [Argumentos e Flags CLI](#argumentos-e-flags-cli)
- [Exemplos de Uso](#exemplos-de-uso)
- [Estrutura do Projeto](#-estrutura-do-projeto)
- [Testes e Qualidade de Código](#-testes-e-qualidade-de-código)
- [Licença](#-licença)
@@ -37,6 +41,7 @@ O **TextNLPClassifierApp** reúne ferramentas de engenharia de dados e processam
1. **`classify.py`**: Motor de classificação semântica e contextual que determina o grau de aderência e inerência de um documento Markdown em relação a uma entidade alvo definida em um **ECP Snapshot (Entity Context Profile)**.
2. **`scripts/extract_google_news.py`**: Extrator de notícias por palavra-chave, idioma e região geográfica que utiliza o motor stealth **Foxcape** (em modo headless), decodificação paralela de URLs para os links reais dos portais de notícias e feedback em tempo real.
3. **`scripts/extract_article_contents.py`**: Extrator e parser de artigos multimotor com navegação stealth Foxcape headless e extração combinada via **Trafilatura**, **Newspaper4k** (NLP) e **Readability**, consolidando texto higienizado, autores, datas, imagens e resumos em JSON estruturado.
---
@@ -208,6 +213,49 @@ python scripts/extract_google_news.py -q "inteligência artificial" -s | jq '.it
---
## 3. 📰 Extrator e Parser Multimotor de Artigos
### Visão Geral e Tríplice Extração
O script `scripts/extract_article_contents.py` lê os arquivos JSON gerados pelo extrator do Google News (ou qualquer lista contendo `items` com `url`), acessa cada página via **Foxcape** em modo stealth headless (reutilizando uma única sessão de navegador ativa com espera do evento `domcontentloaded`), e executa simultaneamente 3 motores especializados de extração:
1. **Trafilatura**: Texto principal higienizado, autores, data de publicação, categorias, tags, URL canônica e payload estruturado nativo.
2. **Newspaper4k**: Artigo completo, autores, imagens (`top_image` e galeria), resumo automático e palavras-chave (*keywords*) extraídas por NLP nativo.
3. **Readability (`readability-lxml`)**: Miolo limpo em HTML sem anúncios ou scripts supérfluos, títulos e texto puro formatado.
O JSON final consolidado é salvo em `out/` com descarte de strings HTML brutas para manter o arquivo leve e veloz.
### Argumentos e Flags CLI
| Parâmetro | Tipo | Padrão | Descrição |
|---|---|---|---|
| `-i, --input` | Caminho (obrigatório) | — | Arquivo JSON de busca de notícias (ex: `out/river_plate.json`). |
| `-o, --output` | Caminho (opcional) | `<input_stem>_extracted.json` | Arquivo JSON de destino consolidado. |
| `-l, --limit` | Inteiro (opcional) | Todos | Limita a quantidade máxima de notícias processadas. |
| `--lang, --language` | String (opcional) | Do JSON / `en` | Sobrescreve o código de idioma para o NLP do Newspaper4k (ex: `pt`, `es`, `en`). |
| `-t, --timeout` | Inteiro (opcional) | `30` | Timeout em segundos por página no Foxcape. |
| `-s, --silent` | Flag booleana | `False` | Suprime logs informativos de progresso no `stderr`. |
### Exemplos de Uso
#### 1. Extração Completa Automática
```bash
python scripts/extract_article_contents.py -i out/river_plate.json
# Gera automaticamente out/river_plate_extracted.json
```
#### 2. Amostragem Rápida (Limit 2 Notícias)
```bash
python scripts/extract_article_contents.py -i out/river_plate.json --limit 2
```
#### 3. Destino Customizado e Timeout Ajustado
```bash
python scripts/extract_article_contents.py -i out/petrobras_result.json -o out/petrobras_full.json --timeout 45
```
---
## 📁 Estrutura do Projeto
```text
@@ -215,19 +263,21 @@ TextNLPClassifierApp/
├── classify.py # CLI principal do Classificador de Inerência
├── scripts/
│ ├── __init__.py # Pacote utilitário de scripts
│ └── extract_google_news.py # CLI de Extração de Manchetes do Google News
│ ├── extract_google_news.py # CLI de Extração de Manchetes do Google News
│ └── extract_article_contents.py # CLI de Extração e Parsing Multimotor de Artigos
├── src/ # Módulos centrais do classificador
│ ├── classifier.py # Orquestrador de classificação (Tier 1, 2, 3)
│ ├── models.py # Modelos de dados e esquemas (ECPSnapshot, Decision)
│ ├── preprocessor.py # Normalização de texto e detecção de idioma
│ └── adapters/ # Adaptadores opcionais de Embeddings e LLM
├── specs/ # Especificações e planos arquiteturais (Speckit)
│ ├── 001-nlp-classifier/ # Especificações do classificador
│ └── 002-google-news-extractor/ # Especificações do extrator de notícias
│ ├── 001-multilingual-entity-classifier/
│ ├── 002-google-news-extractor/
│ └── 003-article-content-extractor/ # Specs da feature de extração multimotor
├── tests/ # Suíte de testes automatizados
│ ├── fixtures/ # Amostras de ECP, Markdown e XML RSS
│ ├── test_classifier.py # Testes unitários do classificador
│ └── test_extract_google_news.py # Testes unitários e testes E2E ao vivo
│ ├── test_classifier.py
│ ├── test_extract_google_news.py
│ └── test_extract_article_contents.py # Testes do extrator de conteúdo
├── requirements.txt # Dependências do projeto
├── pyproject.toml # Configurações de ferramentas (pytest, ruff, mypy)
└── README.md # Documentação principal