Bot automatizado para extracción masiva de datos de juzgados del Poder Judicial Español. Incluye scraping paralelo de múltiples provincias con exportación a Excel e interfaz gráfica moderna (PyQt5).
- 🖥️ Interfaz Gráfica (GUI) moderna con PyQt5
- 🚀 Scraping paralelo de hasta 10 provincias simultáneamente
- 📊 Exportación individual a Excel (.xlsx) por provincia
- 🔄 Paginación automática de resultados
- 🎯 Extracción estructurada: municipio, juzgado, teléfono, dirección, código postal
- 📈 Logs en tiempo real y barra de progreso
- 🗂️ 52 provincias españolas disponibles
- ⚡ Ejecución asíncrona con Playwright
- 💾 Filtrado de filas vacías en Excel
- 🎨 Estilización de encabezados en archivos Excel
- Python >= 3.8
- pip (gestor de paquetes de Python)
- Windows 10/11 (recomendado)
Windows:
install.batLinux/macOS:
chmod +x install.sh
./install.sh-
Crear entorno virtual
python -m venv venv venv\Scripts\activate
-
Instalar dependencias
pip install -r requirements.txt
-
Instalar navegadores de Playwright
playwright install chromium
run_gui.batpython gui.py- ✅ Panel de configuración (modo headless, timeout)
- ✅ Selección visual de provincias con checkboxes
- ✅ Búsqueda y filtrado de provincias
- ✅ Botones rápidos (seleccionar todas, limpiar)
- ✅ Logs en tiempo real con colores
- ✅ Tabla de resultados con estadísticas
- ✅ Barra de progreso visual
- ✅ Botón para abrir carpeta de salida
run.batpython index.py- Modo navegador: Elige entre "Visible" o "Headless"
- Timeout: Ajusta el tiempo de espera (5-120 segundos)
- Buscar: Filtra provincias escribiendo en el cuadro de búsqueda
- Checkboxes: Marca hasta 10 provincias
- Botones rápidos:
✓ Todas: Selecciona las primeras 10 visibles✗ Limpiar: Deselecciona todas
- Click en 🚀 INICIAR SCRAPING
- Observa el progreso en:
- Tab "Logs": Eventos en tiempo real
- Tab "Resultados": Tabla con datos extraídos
- Barra de progreso: Provincias completadas
- Tabla: Código, provincia, registros, estado
- Estadísticas: Total de provincias, registros y archivos
- Botón 📂: Abre la carpeta
output/con los archivos Excel
BOT_EXTRACCION_JDOS/
├── gui.py # 🖥️ Interfaz gráfica PyQt5
├── index.py # 📜 Script principal (consola)
├── run_gui.bat # ▶️ Ejecutar GUI (Windows)
├── run.bat # ▶️ Ejecutar consola (Windows)
├── install.bat # 🔧 Instalador Windows
├── install.sh # 🔧 Instalador Linux/macOS
├── requirements.txt # 📦 Dependencias Python
├── .env # ⚙️ Variables de entorno
├── src/
│ ├── scraper_bot.py # 🤖 Bot principal con Playwright
│ └── __init__.py
├── output/ # 📁 Archivos Excel generados
│ └── *.xlsx
└── README.md # 📖 Este archivo
Cada provincia genera su propio archivo:
poderjudicial_es_15_A_Coruna_20260211_143052.xlsx
poderjudicial_es_28_Madrid_20260211_143105.xlsx
| municipio | juzgado | telefono | direccion | codigo_postal |
|---|---|---|---|---|
| Vigo | Juzgado de Primera Instancia nº 1 | 986 123 456 | Calle Falsa 123 | 36201 |
- ✅ Encabezados con fondo azul y texto blanco
- ✅ Auto-ajuste de columnas
- ✅ Sin filas vacías
- ✅ Formato
.xlsx(compatible con Microsoft Excel, LibreOffice)
HEADLESS=false # true = sin ventana del navegador
TIMEOUT=30000 # Tiempo máximo de espera (ms)'01': 'Araba', '02': 'Albacete', '03': 'Alicante', '04': 'Almeria',
'05': 'Avila', '06': 'Badajoz', '07': 'Illes_Balears', '08': 'Barcelona',
'09': 'Burgos', '10': 'Caceres', '11': 'Cadiz', '12': 'Castellon',
'13': 'Ciudad_Real', '14': 'Cordoba', '15': 'A_Coruna', '16': 'Cuenca',
'17': 'Girona', '18': 'Granada', '19': 'Guadalajara', '20': 'Gipuzkoa',
'21': 'Huelva', '22': 'Huesca', '23': 'Jaen', '24': 'Leon',
'25': 'Lleida', '26': 'La_Rioja', '27': 'Lugo', '28': 'Madrid',
'29': 'Malaga', '30': 'Murcia', '31': 'Navarra', '32': 'Ourense',
'33': 'Asturias', '34': 'Palencia', '35': 'Las_Palmas', '36': 'Pontevedra',
'37': 'Salamanca', '38': 'Santa_Cruz_de_Tenerife', '39': 'Cantabria',
'40': 'Segovia', '41': 'Sevilla', '42': 'Soria', '43': 'Tarragona',
'44': 'Teruel', '45': 'Toledo', '46': 'Valencia', '47': 'Valladolid',
'48': 'Bizkaia', '49': 'Zamora', '50': 'Zaragoza', '51': 'Ceuta',
'52': 'Melilla'- Panel izquierdo: Configuración y selección de provincias
- Panel derecho: Logs en tiempo real y tabla de resultados
- Barra de progreso inferior
- 📋 Logs: Eventos en tiempo real con colores
- 📊 Resultados: Tabla con estadísticas y botón para abrir carpeta
import asyncio
from src.scraper_bot import ScraperBot
async def main():
bot = ScraperBot(config={
'headless': False,
'timeout': 30000
})
await bot.init()
await bot.navigate_to('https://example.com')
# Extraer múltiples elementos
await bot.extract_multiple_items(
"tr[role='row']",
{
"municipio": "th[data-cabecera='Municipio'] span",
"juzgado": "td[data-cabecera='Juzgado'] a"
}
)
# Guardar datos
datos = bot.get_data()
await bot.save_data_csv('output.xlsx')
await bot.close()
asyncio.run(main())playwright install chromiumpip install PyQt5==5.15.10- Verifica que PyQt5 esté instalado:
pip list | findstr PyQt5 - Reinstala dependencias:
pip uninstall PyQt5 pip install PyQt5==5.15.10
- Aumenta el valor de timeout en la GUI (ej: 60000ms)
- Verifica tu conexión a internet
- Comprueba que la URL del Poder Judicial esté accesible
- Verifica permisos de escritura en la carpeta
output/ - Comprueba que openpyxl esté instalado:
pip install openpyxl
- La página puede haber cambiado su estructura
- Verifica los selectores CSS en
scraper_bot.py - Ejecuta en modo Visible para ver qué está pasando
- 1 provincia: 2-5 minutos
- 5 provincias (paralelo): 5-10 minutos
- 10 provincias (paralelo): 10-20 minutos
Tiempos varían según:
- Velocidad de internet
- Número de páginas por provincia
- Cantidad de registros
- Usa modo Headless para mayor velocidad
- Reduce el timeout si la conexión es rápida
- Procesa provincias pequeñas primero
- Respeta los Términos de Servicio del sitio web
- No sobrecargues los servidores (usa delays apropiados)
- Datos personales: Maneja con responsabilidad según RGPD
- Uso educativo/investigación: Este bot es para fines legítimos
- robots.txt: Respeta las directrices del sitio
- ✅ No se almacenan credenciales
- ✅ No se envían datos a terceros
- ✅ Ejecución 100% local
- ✅ Archivos guardados solo en
output/
| Tecnología | Versión | Propósito |
|---|---|---|
| Python | 3.8+ | Lenguaje base |
| Playwright | 1.48.0 | Automatización del navegador |
| PyQt5 | 5.15.10 | Interfaz gráfica |
| openpyxl | 3.11.5 | Exportación Excel |
| asyncio | Built-in | Programación asíncrona |
- ✅ Investigación legal: Recopilación de contactos de juzgados
- ✅ Análisis institucional: Estadísticas del sistema judicial
- ✅ Bases de datos: Construcción de directorios actualizados
- ✅ Automatización: Ahorro de tiempo en tareas repetitivas
- ✅ Monitoreo: Verificación de actualizaciones del directorio
- Exportación a CSV adicional
- Filtros avanzados por tipo de juzgado
- Gráficos de estadísticas en la GUI
- Programación de scraping automático
- Soporte para APIs REST
- Notificaciones por email al finalizar
- Modo oscuro en la GUI
Las contribuciones son bienvenidas:
- Fork el proyecto
- Crea una rama (
git checkout -b feature/nueva-funcionalidad) - Commit tus cambios (
git commit -am 'Añadir funcionalidad') - Push a la rama (
git push origin feature/nueva-funcionalidad) - Abre un Pull Request
Para dudas o problemas:
- Revisa esta documentación
- Comprueba la sección de Solución de Problemas
- Verifica que las dependencias estén instaladas
- Ejecuta en modo Visible para debugging
MIT License - Uso libre para fines educativos y comerciales
- Playwright: Microsoft
- PyQt5: Riverbank Computing
- openpyxl: Eric Gazoni, Charlie Clark
Desarrollado con ❤️ para automatizar la extracción de datos del Poder Judicial Español
¡Happy Scraping! 🏛️✨
await bot.wait_for_element('h1', 5000)
await bot.delay(2000)
await bot.scroll_to_bottom()
#### Interacción
```python
# Hacer clic
await bot.click('button.submit')
# Rellenar input
await bot.fill_input('input[name="search"]', 'mi búsqueda')
# Extraer un elemento simple
datos = await bot.extract_data({
'titulo': 'h1',
'descripcion': 'p.desc'
})
# Extraer múltiples elementos
items = await bot.extract_multiple_items(
'.producto', # Selector del contenedor
{
'nombre': '.titulo',
'precio': '.precio',
'imagen': 'img'
}
)
# Obtener contenido HTML
contenido = await bot.get_page_content()# Guardar como JSON
await bot.save_data('output.json')
# Tomar captura de pantalla
await bot.take_screenshot('pagina.png')# Obtener los datos extraídos
datos = bot.get_data()await bot.close()const { main, ScraperBot } = require('./src/index');
async function miBot() {
const bot = new ScraperBot({ headless: false });
try {
await bot.init();
// Navegar
await bot.navigateTo('https://example.com/productos');
// Esperar elemento
await bot.waitForElement('.producto');
// Extraer datos
await bot.extractMultipleItems('.producto', {
nombre: '.nombre',
precio: '.precio',
disponible: '.stock'
});
// Guardar
await bot.saveData('productos.json');
// Mostrar datos
console.log(bot.getData());
} catch (error) {
console.error('Error:', error);
} finally {
await bot.close();
}
}
miBot();BOT_EXTRACCION_JDOS/
├── src/
│ ├── index.js # Script principal
│ ├── ScraperBot.js # Clase principal del bot
│ └── ejemplos.js # Ejemplos de uso
├── output/ # Datos extraídos (generado automáticamente)
├── .env # Variables de entorno
├── .env.example # Ejemplo de variables
├── .gitignore # Archivos a ignorar
├── package.json # Dependencias
└── README.md # Este archivo
Edita el archivo .env para personalizar:
HEADLESS=false # true = sin navegador
TIMEOUT=30000 # Tiempo de espera en ms
DELAY_BETWEEN_REQUESTS=1000 # Espera entre peticiones
LOG_LEVEL=info # Nivel de logs- ✅ Extracción de precios
- ✅ Recopilación de anuncios
- ✅ Monitoreo de contenido
- ✅ Análisis de competencia
- ✅ Agregación de datos
- ✅ Testing automatizado
- Respetar Terms of Service: Verifica que puedas hacer scraping del sitio
- Delays Apropiados: Usa
delay()para no sobrecargar servidores - User Agent: Usar un user agent real para evitar bloqueos
- Robots.txt: Respeta las directrices en robots.txt
- Datos Sensibles: No incluyas credenciales en el código
npx playwright install- Aumenta
timeouten la configuración - Espera específicamente por elementos:
waitForElement()
- Inspecciona el elemento (F12)
- Verifica que el contenido esté en el DOM
- Usa DevTools para copiar selectores exactos
Para dudas o problemas:
- Revisa los ejemplos en
src/ejemplos.js - Consulta la documentación oficial de Playwright
- Verifica la sintaxis de selectores CSS/XPath
MIT
¡Happy Scraping! 🚀