@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
JavaScript
"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