UNPKG

@personnn/personnnkit

Version:

🇵 PersonnnKit - El Agente Kit Universal. Framework revolucionario para crear agentes de IA con HTML + Python. Simplicidad radical vs frameworks gigantes.

388 lines (329 loc) 13.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.webScrapingAgent = void 0; exports.webScrapingAgent = { id: 'web-scraping', name: 'Web Scraping Agent', description: 'Agente especializado en extracción de datos web con análisis inteligente', category: 'data', dependencies: [ 'fastapi', 'uvicorn', 'requests', 'beautifulsoup4', 'selenium', 'pandas', 'python-dotenv', 'pytest' ], scripts: { 'start': 'npm run dev', 'dev': 'node runtime/dev-server.js', 'build': 'node runtime/build.js', 'test': 'python -m pytest tests/ -v', 'install': 'bash scripts/install.sh', 'setup': 'bash scripts/install.sh', 'scrape': 'python scripts/web_scraper.py' }, files: { 'pages/index.html': `<!DOCTYPE html> <html lang="es"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Web Scraping Agent - PersonnnKit</title> <link href="./css/tailwind.css" rel="stylesheet"> <style> body { background: linear-gradient(135deg, #1e3a8a 0%, #3730a3 50%, #581c87 100%); font-family: 'Inter', sans-serif; color: white; } .glass { background: rgba(255, 255, 255, 0.05); backdrop-filter: blur(20px); border: 1px solid rgba(255, 255, 255, 0.1); border-radius: 16px; } </style> </head> <body class="min-h-screen"> <div class="container mx-auto px-4 py-8"> <div class="max-w-4xl mx-auto"> <div class="text-center mb-12"> <h1 class="text-5xl font-bold mb-4">🕷️ Web Scraping Agent</h1> <p class="text-xl text-gray-300">Extrae datos web de forma inteligente</p> </div> <div class="glass p-8 mb-8"> <h2 class="text-2xl font-semibold mb-6">🎯 Extraer Datos</h2> <input type="url" id="target-url" placeholder="https://ejemplo.com" class="w-full p-3 mb-4 bg-white/10 border border-white/20 rounded-lg"> <div class="flex gap-4"> <button onclick="scrapeWebsite()" class="bg-blue-500 hover:bg-blue-600 px-6 py-3 rounded-lg font-semibold flex-1"> 🚀 Extraer Datos </button> <button onclick="clearResults()" class="bg-gray-500 hover:bg-gray-600 px-6 py-3 rounded-lg font-semibold"> 🗑️ Limpiar </button> </div> </div> <div id="results" class="glass p-6 hidden"> <h3 class="text-xl font-semibold mb-4">📊 Resultados</h3> <div id="scraped-data"></div> </div> <div class="glass p-6"> <h3 class="text-xl font-semibold mb-4">💻 Console</h3> <div id="console" class="bg-black/50 p-4 rounded-lg min-h-32 font-mono text-sm"> <div class="text-green-400">✅ Web Scraping Agent listo...</div> </div> </div> </div> </div> <script> async function scrapeWebsite() { const url = document.getElementById('target-url').value; if (!url) return; const console = document.getElementById('console'); console.innerHTML += '<div class="text-yellow-400">🚀 Iniciando scraping...</div>'; try { const response = await fetch('/api/run-script', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ script: 'web_scraper.py', args: [url] }) }); const result = await response.json(); if (response.ok) { console.innerHTML += '<div class="text-green-400">✅ Scraping completado</div>'; displayResults(result.data); } else { console.innerHTML += \`<div class="text-red-400">❌ Error: \${result.error}</div>\`; } } catch (error) { console.innerHTML += \`<div class="text-red-400">❌ Error: \${error.message}</div>\`; } } function displayResults(data) { const results = document.getElementById('results'); const scrapedData = document.getElementById('scraped-data'); results.classList.remove('hidden'); scrapedData.innerHTML = \` <div class="grid md:grid-cols-2 gap-4"> <div class="bg-black/30 p-4 rounded-lg"> <h4 class="font-semibold text-blue-400">📄 Título</h4> <p>\${data.title || 'No disponible'}</p> </div> <div class="bg-black/30 p-4 rounded-lg"> <h4 class="font-semibold text-green-400">🔗 Enlaces</h4> <p>\${data.links_count || 0} enlaces encontrados</p> </div> </div> <div class="mt-4 bg-black/30 p-4 rounded-lg"> <h4 class="font-semibold text-purple-400">📝 Contenido</h4> <p class="text-sm text-gray-300">\${data.content ? data.content.substring(0, 200) + '...' : 'No disponible'}</p> </div> \`; } function clearResults() { document.getElementById('target-url').value = ''; document.getElementById('results').classList.add('hidden'); document.getElementById('console').innerHTML = '<div class="text-green-400">✅ Web Scraping Agent listo...</div>'; } </script> </body> </html>`, 'scripts/web_scraper.py': `#!/usr/bin/env python3 """ Web Scraping Agent Extrae datos de sitios web de forma inteligente """ import sys import json import requests from bs4 import BeautifulSoup from datetime import datetime import re import os def scrape_website(url): """Extrae datos básicos de un sitio web""" try: headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36' } response = requests.get(url, headers=headers, timeout=10) response.raise_for_status() soup = BeautifulSoup(response.content, 'html.parser') # Extraer información básica title = soup.find('title') title_text = title.get_text().strip() if title else 'Sin título' # Extraer enlaces links = soup.find_all('a', href=True) links_data = [] for link in links[:20]: # Limitar a 20 enlaces href = link.get('href') text = link.get_text().strip() if href and text: links_data.append({'url': href, 'text': text}) # Extraer texto principal for script in soup(["script", "style"]): script.decompose() text_content = soup.get_text() lines = (line.strip() for line in text_content.splitlines()) chunks = (phrase.strip() for line in lines for phrase in line.split(" ")) text = ' '.join(chunk for chunk in chunks if chunk) # Extraer metadatos meta_description = soup.find('meta', attrs={'name': 'description'}) description = meta_description.get('content') if meta_description else '' return { 'url': url, 'title': title_text, 'description': description, 'content': text[:1000], # Primeros 1000 caracteres 'links_count': len(links_data), 'links': links_data, 'word_count': len(text.split()), 'timestamp': datetime.now().strftime("%Y-%m-%d %H:%M:%S") } except Exception as e: raise Exception(f"Error scraping {url}: {str(e)}") def main(): """Función principal""" try: if len(sys.argv) < 2: raise Exception("URL requerida como argumento") url = sys.argv[1] print(f"🕷️ Scraping: {url}") data = scrape_website(url) # Guardar resultados output_dir = "data" os.makedirs(output_dir, exist_ok=True) timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") filename = f"scraping_{timestamp}.json" filepath = os.path.join(output_dir, filename) with open(filepath, 'w', encoding='utf-8') as f: json.dump(data, f, indent=2, ensure_ascii=False) result = { "status": "success", "message": "Scraping completado exitosamente", "data": data, "file": filepath } return json.dumps(result, indent=2, ensure_ascii=False) except Exception as e: error_result = { "status": "error", "message": str(e), "timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S") } return json.dumps(error_result, indent=2, ensure_ascii=False) if __name__ == "__main__": output = main() print("\\n" + "="*50) print("JSON OUTPUT:") print(output)`, 'tests/test_scraping.py': `#!/usr/bin/env python3 """ Tests para el Web Scraping Agent """ import pytest import json import sys import os sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', 'scripts')) def test_scrape_basic(): """Test básico de scraping""" try: from web_scraper import scrape_website # Test con una URL simple (puede fallar si no hay internet) # En un entorno real, usarías un mock test_html = """ <html> <head><title>Test Page</title></head> <body> <h1>Hello World</h1> <a href="/test">Test Link</a> </body> </html> """ # Este test requeriría un mock del requests # Por ahora solo verificamos que la función existe assert callable(scrape_website) print("✅ Test scrape_basic pasó correctamente") except Exception as e: pytest.fail(f"Test scrape_basic falló: {str(e)}") if __name__ == "__main__": print("🧪 Ejecutando tests del Web Scraping Agent...") test_scrape_basic() print("\\n✅ Tests completados!")`, 'scripts/install.sh': `#!/bin/bash # Script de instalación para Web Scraping Agent # Evitar bucle infinito - si ya estamos instalando, salir if [ "$PERSONNNKIT_INSTALLING" = "true" ]; then echo "⚠️ Instalación ya en progreso, evitando bucle infinito..." exit 0 fi # Marcar que estamos instalando export PERSONNNKIT_INSTALLING=true echo "🚀 Instalando Web Scraping Agent..." # Verificar Python if ! command -v python3 &> /dev/null; then echo "❌ Python3 no está instalado" exit 1 fi # Crear entorno virtual si no existe if [ ! -d "venv" ]; then echo "📦 Creando entorno virtual..." python3 -m venv venv fi # Activar entorno virtual echo "🔄 Activando entorno virtual..." source venv/bin/activate # Actualizar pip echo "⬆️ Actualizando pip..." pip install --upgrade pip # Instalar dependencias Python echo "📚 Instalando dependencias Python..." pip install fastapi uvicorn requests beautifulsoup4 selenium pandas python-dotenv pytest # Verificar Chrome/Chromium para Selenium echo "🌐 Verificando navegador para Selenium..." if ! command -v google-chrome &> /dev/null && ! command -v chromium-browser &> /dev/null; then echo "⚠️ Chrome/Chromium no encontrado. Instalando..." if command -v brew &> /dev/null; then brew install --cask google-chrome elif command -v apt-get &> /dev/null; then sudo apt-get update && sudo apt-get install -y chromium-browser else echo "⚠️ Por favor instala Chrome o Chromium manualmente para usar Selenium" fi fi # Crear directorios necesarios echo "📁 Creando directorios..." mkdir -p data mkdir -p public/css # Hacer scripts ejecutables echo "🔧 Configurando permisos..." chmod +x scripts/*.py chmod +x scripts/*.sh # Limpiar variable de entorno unset PERSONNNKIT_INSTALLING echo "✅ Instalación completada!" echo "" echo "🎯 Para usar el scraper:" echo "1. Inicia el servidor: npm run dev" echo "2. Abre http://localhost:3333 en tu navegador" echo "" echo "🧪 Para ejecutar tests: npm run test"`, 'README.md': `# Web Scraping Agent Agente especializado en extracción de datos web con análisis inteligente. ## 🎯 Características - ✅ Extracción de contenido web - ✅ Análisis de enlaces y metadatos - ✅ Interfaz web intuitiva - ✅ Guardado automático de resultados ## 🚀 Uso 1. Ingresa una URL en la interfaz 2. Haz clic en "Extraer Datos" 3. Revisa los resultados extraídos --- Construido con ❤️ usando **PersonnnKit**` } }; //# sourceMappingURL=web-scraping.js.map