init: scripts diversos (crawlers, conversores, scrapers)

This commit is contained in:
2026-03-05 20:38:36 +00:00
commit 6ac6f4be2a
925 changed files with 850330 additions and 0 deletions

195
scraper/consolidate_knowledge.py Executable file
View File

@@ -0,0 +1,195 @@
"""
consolidate_knowledge.py - Consolidar 118 ficheiros JSON num único ficheiro
Author: Descomplicar® Crescimento Digital
Link: https://descomplicar.pt
Copyright: 2025 Descomplicar®
"""
import os
import json
from pathlib import Path
from datetime import datetime
from typing import Dict, List
import statistics
# Configurações
INPUT_DIR = "/media/ealmeida/Dados/GDrive/Cloud/Clientes_360/CTF_Carstuff/KB/Scrapper/sites/knowledge_base_final"
OUTPUT_FILE = "/media/ealmeida/Dados/GDrive/Cloud/Clientes_360/CTF_Carstuff/KB/Scrapper/sites/knowledge_base_consolidated.json"
def load_all_knowledge() -> List[Dict]:
"""Carrega todos os ficheiros JSON."""
all_knowledge = []
input_path = Path(INPUT_DIR)
json_files = sorted(input_path.glob("knowledge_*.json"))
print(f"📂 Encontrados {len(json_files)} ficheiros JSON")
print("🔄 A carregar...")
for idx, json_file in enumerate(json_files, 1):
try:
with open(json_file, 'r', encoding='utf-8') as f:
data = json.load(f)
# Adicionar metadata do ficheiro
data['_source_file'] = json_file.name
data['_id'] = idx
all_knowledge.append(data)
if idx % 20 == 0:
print(f"{idx}/{len(json_files)} carregados...")
except Exception as e:
print(f" ⚠️ Erro em {json_file.name}: {e}")
continue
print(f"{len(all_knowledge)} ficheiros carregados com sucesso")
return all_knowledge
def generate_statistics(knowledge_list: List[Dict]) -> Dict:
"""Gera estatísticas sobre o conhecimento consolidado."""
stats = {
'total_entradas': len(knowledge_list),
'total_casos_completos': 0,
'categorias': {},
'tipos_conteudo': {},
'nivel_expertise': {},
'materiais_principais': {},
'keywords_tecnicas': {},
'sites_fonte': {},
'aplicabilidades': {}
}
for entry in knowledge_list:
# Contar casos completos
casos = entry.get('casos_completos', [])
stats['total_casos_completos'] += len(casos)
# Categorias
cat = entry.get('categoria_aplicacao', 'desconhecido')
stats['categorias'][cat] = stats['categorias'].get(cat, 0) + 1
# Tipos de conteúdo
tipo = entry.get('tipo_conteudo', 'desconhecido')
stats['tipos_conteudo'][tipo] = stats['tipos_conteudo'].get(tipo, 0) + 1
# Nível de expertise
nivel = entry.get('nivel_expertise', 'desconhecido')
stats['nivel_expertise'][nivel] = stats['nivel_expertise'].get(nivel, 0) + 1
# Materiais principais
materiais = entry.get('materiais_discutidos', {}).get('principais', [])
for mat in materiais:
stats['materiais_principais'][mat] = stats['materiais_principais'].get(mat, 0) + 1
# Keywords técnicas
keywords = entry.get('keywords_tecnicas', [])
for kw in keywords:
stats['keywords_tecnicas'][kw] = stats['keywords_tecnicas'].get(kw, 0) + 1
# Sites fonte
source = entry.get('_source_file', 'unknown')
site = source.split('_')[1] if '_' in source else 'unknown'
stats['sites_fonte'][site] = stats['sites_fonte'].get(site, 0) + 1
# Aplicabilidades
apps = entry.get('aplicabilidade', [])
for app in apps:
stats['aplicabilidades'][app] = stats['aplicabilidades'].get(app, 0) + 1
# Ordenar por frequência (top 20)
stats['materiais_principais'] = dict(sorted(
stats['materiais_principais'].items(),
key=lambda x: x[1],
reverse=True
)[:20])
stats['keywords_tecnicas'] = dict(sorted(
stats['keywords_tecnicas'].items(),
key=lambda x: x[1],
reverse=True
)[:30])
return stats
def consolidate_knowledge():
"""Função principal de consolidação."""
print("═══════════════════════════════════════════════════════════")
print(" CTF CARSTUFF - CONSOLIDAÇÃO KNOWLEDGE BASE")
print("═══════════════════════════════════════════════════════════")
print()
# Carregar todos os ficheiros
all_knowledge = load_all_knowledge()
if not all_knowledge:
print("❌ Nenhum conhecimento carregado!")
return
print()
print("📊 A gerar estatísticas...")
# Gerar estatísticas
statistics_data = generate_statistics(all_knowledge)
# Estrutura final consolidada
consolidated = {
'metadata': {
'created_at': datetime.now().isoformat(),
'total_entries': len(all_knowledge),
'total_complete_cases': statistics_data['total_casos_completos'],
'source_directory': INPUT_DIR,
'description': 'Knowledge base consolidada de estofamento automotivo, náutico e aeronáutico',
'extraction_criteria': 'Apenas casos completos: Problema → Solução → Resultado'
},
'statistics': statistics_data,
'knowledge_base': all_knowledge
}
# Guardar ficheiro consolidado
print(f"💾 A guardar em: {OUTPUT_FILE}")
output_path = Path(OUTPUT_FILE)
with open(output_path, 'w', encoding='utf-8') as f:
json.dump(consolidated, f, indent=2, ensure_ascii=False)
# Verificar tamanho
file_size = output_path.stat().st_size / (1024 * 1024) # MB
print()
print("═══════════════════════════════════════════════════════════")
print(" CONSOLIDAÇÃO CONCLUÍDA")
print("═══════════════════════════════════════════════════════════")
print(f"📊 Total de entradas: {len(all_knowledge)}")
print(f"📦 Total de casos completos: {statistics_data['total_casos_completos']}")
print(f"📁 Tamanho do ficheiro: {file_size:.2f} MB")
print(f"💾 Ficheiro: {OUTPUT_FILE}")
print()
print("📈 ESTATÍSTICAS TOP:")
print()
print("🏷️ Categorias:")
for cat, count in statistics_data['categorias'].items():
print(f" - {cat}: {count}")
print()
print("📋 Tipos de conteúdo:")
for tipo, count in statistics_data['tipos_conteudo'].items():
print(f" - {tipo}: {count}")
print()
print("🎓 Nível de expertise:")
for nivel, count in statistics_data['nivel_expertise'].items():
print(f" - {nivel}: {count}")
print()
print("🏢 Sites fonte:")
for site, count in statistics_data['sites_fonte'].items():
print(f" - {site}: {count}")
print()
print("🔝 Top 10 Materiais:")
for idx, (mat, count) in enumerate(list(statistics_data['materiais_principais'].items())[:10], 1):
print(f" {idx}. {mat}: {count} menções")
print()
print("═══════════════════════════════════════════════════════════")
if __name__ == '__main__':
consolidate_knowledge()