# 🧠 TextNLPClassifierApp [![Python Version](https://img.shields.io/badge/Python-3.10%20%7C%203.11%20%7C%203.12%20%7C%203.13%20%7C%203.14-blue.svg)](https://www.python.org/) [![License](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE) [![Code Style](https://img.shields.io/badge/Code%20Style-Ruff-black.svg)](https://github.com/astral-sh/ruff) [![Type Checked](https://img.shields.io/badge/Type%20Check-Mypy-blue.svg)](https://mypy-lang.org/) [![Tests](https://img.shields.io/badge/Tests-Pytest%20(100%25%20Passing)-brightgreen.svg)](tests/) > Plataforma modular em Python para **Classificação Multilíngue de Inerência de Entidades (NLP/LLM/ECP)** e **Extração Inteligente de Manchetes de Notícias com Evasão Anti-Bot (Google News RSS & Foxcape)**. --- ## 📑 Tabela de Conteúdos - [Visão Geral](#-visão-geral) - [Instalação e Setup](#-instalação-e-setup) - [1. Classificador de Conteúdo e Inerência (NLP / LLM / ECP)](#1--classificador-de-conteúdo-e-inerência-nlp--llm--ecp) - [O que é e Como Funciona](#o-que-é-e-como-funciona) - [Arquitetura de Classificação em 3 Tiers](#arquitetura-de-classificação-em-3-tiers) - [Categorias de Decisão](#categorias-de-decisão) - [Formato do ECP Snapshot e Markdown](#formato-do-ecp-snapshot-e-markdown) - [Exemplos de Uso CLI](#exemplos-de-uso-cli) - [2. Extrator de Manchetes do Google News](#2--extrator-de-manchetes-do-google-news) - [O que é e Como Funciona](#o-que-é-e-como-funciona-1) - [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) - [Estrutura do Projeto](#-estrutura-do-projeto) - [Testes e Qualidade de Código](#-testes-e-qualidade-de-código) - [Licença](#-licença) --- ## 🌟 Visão Geral O **TextNLPClassifierApp** reúne ferramentas de engenharia de dados e processamento de linguagem natural: 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. --- ## ⚙️ Instalação e Setup ### 1. Clonar o Repositório e Criar Ambiente Virtual ```bash git clone cd TextNLPClassifierApp python -m venv .venv # Windows (PowerShell) .venv\Scripts\Activate.ps1 # Linux/macOS source .venv/bin/activate ``` ### 2. Instalar Dependências ```bash pip install -r requirements.txt ``` ### 3. Baixar Binários do Navegador Stealth (Camoufox) O motor **Foxcape** utiliza o navegador customizado Camoufox para evasão avançada de fingerprinting: ```bash python -m camoufox fetch ``` --- ## 1. 🧠 Classificador de Conteúdo e Inerência (NLP / LLM / ECP) ### O que é e Como Funciona O classificador avalia se um texto em Markdown trata centralmente, contextualmente ou apenas de forma superficial de uma determinada entidade alvo (ex: empresa, figura pública, clube, conceito). A entidade é descrita através de um **ECP Snapshot (Entity Context Profile)** contendo nomes canônicos, apelidos (*aliases*), âncoras temáticas, âncoras negativas e entidades de contexto relacional. O sistema suporta nativamente **6 idiomas**: Português (`pt`), Inglês (`en`), Espanhol (`es`), Francês (`fr`), Alemão (`de`) e Italiano (`it`). ### Arquitetura de Classificação em 3 Tiers ```mermaid flowchart TD MD[Markdown Content] --> Pre[Pré-processamento & Detecção de Idioma] ECP[ECP Snapshot JSON] --> Pre Pre --> T1[Tier 1: Determinístico & Regras NLP] T1 -- Alta Confiança --> Decision[Decisão Final JSON] T1 -- Score Intermediário / Ambíguo --> T2{Tier 2 Habilitado?} T2 -- Sim --> Emb[Tier 2: Similaridade Semântica / Embeddings] T2 -- Não --> Decision Emb -- Inconclusivo --> T3{Tier 3 Habilitado?} T3 -- Sim --> LLM[Tier 3: LLM Inherence Adapter] T3 -- Não --> Decision LLM --> Decision ``` * **Tier 1 (Determinístico / NLP Leve)**: Análise de frequência de termos, detecção de âncoras temáticas no primeiro terço do documento, contagem de aliases e penalização por âncoras negativas. * **Tier 2 (Vetorial / Embeddings)** *(Opcional: `--enable-embeddings`)*: Projeção vetorial e cálculo de cosseno entre o perfil da entidade e os parágrafos do documento. * **Tier 3 (LLM Fallback)** *(Opcional: `--enable-llm`)*: Consulta a modelo de linguagem para desambiguação de casos limiares e sutilezas semânticas. ### Categorias de Decisão | Categoria | Descrição | | :--- | :--- | | `DIRECT_INHERENT` | O conteúdo é centrado e focado diretamente na entidade alvo. | | `CONTEXTUAL_INHERENT` | A entidade é relevante no contexto da discussão, mesmo dividindo foco com outros temas. | | `TANGENTIAL` | A entidade é mencionada apenas de passagem ou em listas ilustrativas. | | `NOT_RELATED` | O conteúdo não possui relação substantiva com a entidade alvo. | ### Formato do ECP Snapshot e Markdown #### Exemplo de ECP Snapshot (`ecp_sample.json`): ```json { "target_entity_id": "ent_river_plate", "target_name": "River Plate", "aliases": ["Club Atlético River Plate", "Millonario", "El Más Grande"], "domain": "sports/football", "anchors": ["Monumental", "Copa Libertadores", "Marcelo Gallardo", "Copa Sudamericana"], "negative_anchors": ["Boca Juniors vitória", "Flamengo campeão"], "graph_version": "1.0.0", "related_entities": [ { "entity_id": "ent_gallardo", "name": "Marcelo Gallardo", "relation_type": "manager", "weight": 0.85, "aliases": ["Muñeco"] } ] } ``` ### Exemplos de Uso CLI ```bash # Classificação Determinística padrão (Tier 1) python classify.py --ecp tests/fixtures/sample_ecp.json --content tests/fixtures/sample_article.md # Salvar resultado em arquivo JSON formatado python classify.py --ecp ecp.json --content artigo.md --output out/resultado_classificacao.json # Habilitar camadas adicionais (Embeddings e LLM) python classify.py --ecp ecp.json --content artigo.md --enable-embeddings --enable-llm ``` --- ## 2. 📰 Extrator de Manchetes do Google News ### O que é e Como Funciona O script [`scripts/extract_google_news.py`](file:///c:/Users/aferr/Projects/AFTech/DunaMedia/TextNLPClassifierApp/scripts/extract_google_news.py) é um extrator CLI autônomo projetado para consultar o feed RSS do Google News com máxima velocidade, resiliência e integridade de dados. ### Diferenciais Técnicos * 🛡️ **Foxcape Headless Anti-Bot**: Utiliza o motor `foxcape` com `FoxcapeConfig(headless=True)` e Camoufox para evitar bloqueios 429/403 e captchas em segundo plano sem abrir navegadores visuais. * 🔗 **Resolução Automática de URLs Reais**: Decodifica em paralelo (`ThreadPoolExecutor`) as URLs intermediárias do Google News (`news.google.com/rss/articles/...`) entregando diretamente o link final do portal de notícia (*Olé, TyC Sports, ge, ESPN, BBC, etc.*). * 🧹 **Higienização de HTML**: Sanitiza resumos e descrições, eliminando tags HTML residuais (`
    `, `
  1. `, ``, ``). * 📊 **Logging Informativo no Terminal**: Emite o status passo a passo no canal `stderr` sem poluir a saída JSON em `stdout` (100% compatível com pipes e `jq`). * 🌎 **Mapeamento de Idioma & Região**: Mapeia automaticamente códigos regionais (`pt` → `BR:pt-BR`, `es` → `AR:es-419`, `en` → `US:en-US`) permitindo customização com `--locale`. ### Argumentos e Flags de Linha de Comando | Flag | Tipo | Obrigatório | Padrão | Descrição | | :--- | :--- | :--- | :--- | :--- | | `-q`, `--query`, `--keyword` | `str` | **Sim** | — | Termo de pesquisa (ex: `"River Plate"`). | | `-l`, `--lang`, `--language` | `str` | Não | `"pt"` | Código do idioma (`pt`, `es`, `en`, `de`, `fr`, `it`). | | `--locale`, `--country` | `str` | Não | `None` | País/região editorial (`BR`, `AR`, `MX`, `US`, `GB`, `ES`). | | `-p`, `--max-pages` | `int` | Não | `1` | Quantidade de páginas (1 a 10; cada página traz 10 itens). | | `-o`, `--output` | `str` | Não | `None` | Caminho para salvar o arquivo JSON. | | `--pretty` | `flag` | Não | `False` | Formata o JSON no terminal com indentação de 2 espaços. | | `--no-resolve-urls` | `flag` | Não | `False` | Desativa a resolução e mantém as URLs brutas do Google News. | | `-s`, `--silent`, `--quiet` | `flag` | Não | `False` | Suprime os logs de progresso no `stderr`. | ### Exemplos Práticos de Uso #### 1. River Plate (Argentina / Espanhol / 2 Páginas / Salvar em Arquivo) ```bash python scripts/extract_google_news.py -q "River Plate" -l es --locale AR -p 2 -o out/river_plate.json ``` * **Saída no Terminal**: ```text [INFO] 🔍 Consultando Google News: 'River Plate' (idioma: es, locale: AR, max_pages: 2)... [INFO] 📥 Feed RSS recebido (162117 bytes). [INFO] 📰 20 artigos extraídos do feed XML. [INFO] 🔗 Decodificando 20 URLs do Google News para os portais reais... [INFO] ✅ 20/20 URLs resolvidas com sucesso para os domínios de origem. [INFO] 💾 Arquivo salvo com sucesso: 'out/river_plate.json' (20 notícias). ``` #### 2. Cruzeiro (Brasil / Português / Formatado no Terminal) ```bash python scripts/extract_google_news.py --query "Cruzeiro" --lang pt --locale BR --pretty ``` #### 3. Fórmula 1 (Inglaterra / Inglês) ```bash python scripts/extract_google_news.py --query "Formula 1" --lang en --locale GB --pretty ``` #### 4. Filtragem com `jq` em Modo Silencioso ```bash python scripts/extract_google_news.py -q "inteligência artificial" -s | jq '.items[].url' ``` --- ## 📁 Estrutura do Projeto ```text 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 ├── 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 ├── 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 ├── requirements.txt # Dependências do projeto ├── pyproject.toml # Configurações de ferramentas (pytest, ruff, mypy) └── README.md # Documentação principal ``` --- ## 🧪 Testes e Qualidade de Código O repositório possui cobertura com testes unitários, testes de integração e testes End-to-End (E2E) com requisição de rede ao vivo: ```bash # Executar todos os testes do projeto pytest -v # Executar especificamente os testes do Extrator de Notícias pytest tests/test_extract_google_news.py -v # Validação e correção automática de formatação com Ruff ruff check --fix . ruff format . # Verificação estática de tipos com Mypy mypy scripts/ src/ ``` --- ## 📄 Licença Este projeto está licenciado sob os termos da licença **MIT**. Consulte o arquivo `LICENSE` para mais detalhes.