🇪🇸 BOE Explorer

February 18, 2026 · View on GitHub

BOE Explorer Dashboard

🌐 Demo en vivo: https://test.pro-eurtec.com/

Plataforma open-source de análisis, enriquecimiento y visualización de datos públicos del Boletín Oficial del Estado (BOE), Base de Datos Nacional de Subvenciones (BDNS), Boletín Oficial del Registro Mercantil (BORME), Congreso de los Diputados y Promesas Electorales.

PHP 8.x Chart.js 4.4.1 Tailwind CSS License: MIT Demo


📋 Índice


🎯 Descripción

BOE Explorer es una plataforma 100% open-source que agrega, enriquece y cruza datos de las cinco principales fuentes de datos abiertos del Estado español:

FuenteDatos
BOELegislación, licitaciones, adjudicaciones, nombramientos, convenios
BDNSSubvenciones públicas, convocatorias, destinatarios
BORMERegistro mercantil, socios, administradores, cargos empresariales
CongresoVotaciones parlamentarias, asistencia, transferencias de voto, correlación por CCAA
PromesasPromesas electorales, cumplimiento, patrimonio de diputados, contradicciones políticas

El objetivo es democratizar el acceso a la información pública, facilitando la detección de patrones de gasto, concentración empresarial, actividad parlamentaria y seguimiento de compromisos electorales.


✨ Características principales

📊 Dashboard multi-fuente

  • Agregación diaria automática de BOE + BDNS + BORME
  • KPIs en tiempo real: documentos del día, tendencias semanales/mensuales
  • Gráficos interactivos con drill-down (click en cualquier segmento para ver el detalle)

🔍 Motor de búsqueda avanzado

  • Búsqueda federada unificada (BOE + Licitaciones + Subvenciones simultáneamente)
  • Filtros combinables: empresa, NIF/CIF, departamento, tipo, CCAA, rango de importes, procedimiento
  • Búsqueda accent-insensitive (encontrar "García" buscando "garcia")

💰 Análisis de licitaciones

  • Enriquecimiento XML individual de cada licitación
  • Extracción de importes (6 patrones prioritarios: adjudicación > estimado > presupuesto)
  • Datos de adjudicatario + NIF, CPV, procedimiento, ofertas mayor/menor (13.2/13.3)
  • Desglose por departamento, empresa, tipo de contrato, CCAA, sector y timeline

🔗 Motor de referencias cruzadas

  • Correlación automática entre documentos BOE y licitaciones
  • Scoring multi-signal con confianza ponderada (0.0–1.0)
  • Detección de afinidad departamental, coincidencia de keywords, solapamiento de términos

🏢 Inteligencia empresarial (BORME)

  • Parsing de PDFs del Registro Mercantil con pdftotext
  • Extracción de socios, administradores, consejeros (30+ tipos de cargo)
  • Seguimiento de nombramientos y ceses con estado activo/cesado
  • 92,000+ empresas indexadas

🎯 Análisis de subvenciones (BDNS)

  • Clasificación por sector, nivel administrativo, entidad y destino
  • Detección de destinos internacionales (80+ países, 6 regiones)
  • Timeline de convocatorias con tendencias

⚠️ Alertas de transparencia

  • Concentración de contratos por empresa (flag ≥3, alerta alta ≥5)
  • Recurrencia empresa-departamento
  • Clasificación de 17 tipos de entidad jurídica española por NIF/CIF

🏛 Congreso de los Diputados

  • Votaciones parlamentarias: 1,666 votaciones de 114 sesiones (XV Legislatura)
  • Diagrama Sankey de transferencias de voto entre partidos
  • Muro de la Vergüenza: ranking de diputados por asistencia y patrones de voto
  • Correlación por CCAA: análisis de afinidad de voto entre comunidades autónomas
  • Buscador de diputados: búsqueda por nombre, filtro por grupo parlamentario, ordenación por nombre/asistencia/votos
  • Tabla de resultados con 8 columnas: ranking, nombre, grupo, asistencia, sí, no, abstención, no_vota

📊 Promesas Electorales

  • Promesómetro: barras de progreso apiladas por partido (PSOE, Sumar, PP, VOX) con indicadores gobierno/oposición
  • Buscador de promesas: filtro por texto libre, partido y estado (cumplida, parcial, en_trámite, incumplida, rechazada)
  • Nubes de Palabras: comparativa programa electoral vs. actividad legislativa real, con pestañas por partido
  • Timeline de Contradicciones: 7 casos documentados de "lo que dijeron" vs. "lo que hicieron" con referencias BOE
  • Patrimonio de diputados: tabla comparativa antes/después de ser electos + gráfico de variación patrimonial
  • 34 promesas reales con evidencias, timeline y estado de cumplimiento
  • Extracción automatizada de keywords desde PDFs de programas electorales (vía pdftotext)

🏗 Arquitectura del sistema

┌─────────────────────────────────────────────────────────────┐
│                      FRONTEND (SPA)                          │
│                index.html (~4,100 líneas)                     │
│  Vanilla JS · Chart.js 4.4.1 · Tailwind CSS · WordCloud      │
│  90+ funciones · 25+ gráficos · Sankey · Dark/Light mode     │
└───────────────────────────┬─────────────────────────────────┘
                            │ HTTP/JSON
┌───────────────────────────┴─────────────────────────────────┐
│                       API REST (PHP 8.x)                     │
│                    api/index.php (router)                     │
│                      18 endpoints                            │
├──────────┬──────────┬──────────┬──────────┬─────────────────┤
│ boe_     │ bdns_    │ borme_   │ congreso │ promesas_parser │
│ parser   │ parser   │ parser   │ _parser  │   367 LoC       │
│ 375 LoC  │ 680 LoC  │ 727 LoC  │ 568 LoC  │                 │
├──────────┴──────────┴──────────┴──────────┴─────────────────┤
│         data_store.php (743 LoC) · cross_ref (194 LoC)       │
│      Búsqueda · Análisis · Sectores · Empresas · Keywords    │
├─────────────────────────────────────────────────────────────┤
│                    config.php (151 LoC)                       │
│           Cache · HTTP client · Normalización                │
└───────────────────────────┬─────────────────────────────────┘
                            │ Flat-file JSON
┌───────────────────────────┴─────────────────────────────────┐
│                   ALMACENAMIENTO                             │
│   api/data/boe/YYYY-MM-DD.json  (557+ días)                  │
│   api/data/bdns/convocatorias.json (10K+ registros)           │
│   api/data/borme/YYYY-MM-DD.json (42+ días)                   │
│   api/data/congreso/votaciones/ (114 sesiones, 1666 JSON)    │
│   api/data/promesas/promesas.json (34 promesas, patrimonio)  │
│   api/cache/*.json (TTL: 5-60 min)                           │
└─────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────┐
│                FUENTES DE DATOS EXTERNAS                      │
│                                                              │
│  BOE XML ── BDNS REST ── BORME PDF ── Congreso Datos Abiertos│
│  boe.es    hacienda.gob   boe.es/borme  congreso.es/opendata │
└─────────────────────────────────────────────────────────────┘

📡 Fuentes de datos

FuenteProtocoloURL BaseFormato
BOE (Boletín Oficial del Estado)REST/XMLhttps://www.boe.es/datosabiertos/apiXML (sumarios + documentos individuales)
BDNS (Base Nacional de Subvenciones)REST/JSONhttps://www.pap.hacienda.gob.es/bdnstrans/apiJSON (con autenticación XSRF + cookies)
BORME (Registro Mercantil)REST/JSON + PDFhttps://www.boe.es/datosabiertos/api/borme/JSON (sumario) + PDF (actas)
Congreso (Datos Abiertos)REST/JSONhttps://www.congreso.es/es/opendata/votacionesJSON (sesiones + votaciones individuales)
Contratación del EstadoATOM Feedhttps://contrataciondelestado.esXML/ATOM (parser legacy)

🛠 Stack tecnológico

Backend

TecnologíaUso
PHP 8.x (vanilla, sin framework)API REST, parsers, procesamiento
cURL (ext-curl)HTTP client para APIs externas
pdftotext (poppler-utils)Extracción de texto de PDFs BORME
JSON flat-fileAlmacenamiento sin base de datos
OPcacheCaché de bytecode PHP

Frontend

TecnologíaVersiónUso
Vanilla JavaScriptES2021+SPA, 90+ funciones, async/await
Chart.js4.4.125+ gráficos interactivos con drill-down
chartjs-chart-sankey0.12.1Diagrama Sankey de transferencias de voto
chartjs-chart-wordcloud4.4.3Nubes de palabras (programa vs legislativo)
Tailwind CSS3.x (CDN)Diseño responsive, dark mode
Inter (Google Fonts)Variable weightTipografía
Material SymbolsOutlinedIconografía

Infraestructura

ComponenteDetalle
ServidorDebian Linux, Virtualmin
PHP-FPMWorker pool con OPcache
CronActualización diaria automática
CachéArchivos JSON, TTL configurable (5–60 min)

Total: ~11,000+ líneas de código (sin datos ni tests)


🧠 Algoritmos y NLP

1. Motor de Referencias Cruzadas

Archivo: api/cross_reference.php (194 LoC)

Scoring multi-señal que combina 5 dimensiones para calcular la confianza (0.0 – 1.0) de la correlación entre un documento BOE y una licitación:

SeñalPeso máximoMétodo
Keywords temáticos+0.15/categoría8 categorías × ~10 keywords cada una
Afinidad departamental+0.3013 diccionarios de alias ministeriales
Solapamiento de palabras+0.30Tokens ≥4 caracteres, Jaccard-like
Afinidad tipo documento+0.10Bonus para tipos de contratación
Matching de referencia ID+0.50Coincidencia exacta de identificadores

Niveles de confianza: Alta (≥70%), Media (40-70%), Baja (20-40%), Muy baja (<20%)

2. Clasificador de sectores

Archivos: api/data_store.php + api/bdns_parser.php

Clasificador NLP basado en keywords con 14 sectores y 100+ keywords por conjunto, aplicado tanto a licitaciones como a subvenciones:

Salud · Educación · Cultura · Vivienda · Medio Ambiente
Agricultura · Industria · Transporte · Empleo · Seguridad
Justicia · Cooperación · Digitalización · Servicios Generales

Técnicas: normalización accent-insensitive, lowercase matching, priorización por especificidad.

3. Parser BORME (NLP sobre PDF)

Archivo: api/borme_parser.php (727 LoC)

Pipeline de extracción:

PDF → pdftotext -layout → Limpieza headers/footers → Split por nº registro
→ Detección de secciones (Nombramientos/Ceses) → Extracción de personas
→ Clasificación de 30+ tipos de cargo → Merge activo/cesado

Cargos reconocidos: Administrador Único, Consejero Delegado, Presidente, Secretario, Apoderado, Liquidador, Auditor, Representante, Socio, y 20+ variantes.

4. Enriquecimiento de licitaciones

Archivo: api/boe_parser.php (375 LoC)

Cada licitación se enriquece individualmente fetching su XML del BOE:

  • 6 patrones de extracción de importe (prioridad: adjudicación > estimado > presupuesto > oferta)
  • Parsing de números españoles (1.234.567,89 → float)
  • Extracción de adjudicatario + NIF/CIF (campos 12.1, 12.2)
  • Detección PYME, códigos CPV, tipo de procedimiento
  • Ofertas mayor/menor (campos 13.2, 13.3)

5. Detección de destinos internacionales

Archivo: api/bdns_parser.php

Clasificador geo-NLP:

  • 80+ países con variantes de gentilicio y nombre
  • 6 agrupaciones regionales (África, América Latina, Asia, UE, Oriente Medio, Países en desarrollo)
  • Word-boundary regex para keywords cortos (≤6 chars) para evitar falsos positivos

6. Clasificación de entidades jurídicas

Archivo: api/data_store.php

Identificación de 17 tipos de entidad a partir del prefijo NIF/CIF:

A → S.A. | B → S.L. | C → S.Colectiva | D → S.Comanditaria
E → Comunidad | F → Cooperativa | G → Asociación | H → C.Propietarios
J → Civil | N → Extranjera | P → Corporación | Q → Organismo Público
R → Congregación | S → Estatal/Autonómico | U → UTE | V → Otros | W → Sucursal Extranjera

7. Alertas de transparencia (Red Flags)

Detección automática de:

  • Concentración: empresa con ≥3 contratos → flag, ≥5 → alerta alta
  • Recurrencia: misma empresa + mismo departamento ≥2 veces
  • Análisis PYME vs Gran empresa por volumen de adjudicación

8. Parser del Congreso (Votaciones)

Archivo: api/congreso_parser.php (568 LoC)

Pipeline de procesamiento de datos abiertos del Congreso:

API Congreso → Descarga sesiones → JSON votaciones individuales
→ Agregación por diputado (asistencia, votos Sí/No/Abs/NoVota)
→ Cálculo de flujos (Sankey) entre grupos parlamentarios
→ Correlación de voto por CCAA → Rankings (mejores/peores)

Capacidades:

  • 1,666 votaciones procesadas de 114 sesiones (XV Legislatura)
  • 407 diputados únicos (incluye reemplazos)
  • 37 flujos de transferencia de voto entre grupos para diagrama Sankey
  • 19 correlaciones por CCAA para análisis de afinidad territorial
  • Caché de asistencia incremental para rendimiento

9. Parser de Promesas Electorales

Archivo: api/promesas_parser.php (367 LoC)

Sistema de seguimiento de compromisos electorales:

promesas.json → Estadísticas por partido → Búsqueda multi-criterio
→ Extracción de keywords de PDFs (pdftotext) → Cross-ref con BOE
→ API JSON con stats, patrimonio, contradicciones

Funciones principales:

  • promesas_stats() — Agregados por partido: % cumplida, en proceso, incumplida, rechazada
  • promesas_buscar() — Búsqueda multi-criterio: texto, partido, categoría, estado
  • promesas_extract_keywords_from_pdf() — NLP sobre PDFs de programas electorales (tokenización, stopwords español, top-N keywords)
  • promesas_buscar_en_boe() — Cruce de keywords de promesas con datos BOE existentes

Datos curados:

  • 34 promesas reales (PSOE: 12, Sumar: 8, PP: 8, VOX: 6) con estados, evidencias y timeline
  • 8 patrimonios de diputados notables (antes/después de ser electos)
  • 7 contradicciones documentadas con referencias BOE
  • Keywords estimadas de programa vs. actividad legislativa por partido

📡 API REST

Base URL: /api/?action=

Endpoints principales (18)

EndpointParamsDescripción
statusSalud del sistema, versión, conteos
dashboardKPIs del día, tendencias, últimos documentos
documentostexto, departamento, seccion, tipo, fecha_*Búsqueda de documentos BOE (paginado)
licitacionestexto, empresa, nif, tipo, departamento, ccaa, importe_min/max, procedimiento, fecha_*Búsqueda de licitaciones (paginado)
referenciasconfianza_min, limiteReferencias cruzadas BOE↔Licitaciones
resumen-gastoperiodo (diario/semanal/mensual)Análisis de gasto por múltiples dimensiones
analisis-empresasConcentración empresarial + alertas
analisis-tematicoAnálisis temático por keywords
subvencionesAnalytics de BDNS (sector, nivel, destino, timeline)
subvenciones-buscartexto, nivel, sector, fecha_*Búsqueda de convocatorias BDNS (paginado)
subvenciones-chart-detallecampo, valorDrill-down de gráficos BDNS
subvenciones-destino-detalledestinoDetalle por destino internacional
busqueda-globalqBúsqueda federada (BOE + Licitaciones + Subvenciones)
sociosempresaSocios/cargos de empresa desde BORME
borme-statusEstado de procesamiento BORME
departamentosLista de departamentos únicos (30 días)
congresoVotaciones, asistencia, Sankey, correlación CCAA (caché 30 min)
promesasPromesómetro, stats, patrimonio, contradicciones, keywords (caché 1h)

Ejemplo de uso

# Buscar licitaciones de Defensa con importe > 1M€
curl "https://tu-dominio.com/api/?action=licitaciones&departamento=Defensa&importe_min=1000000"

# Buscar socios de Telefónica en BORME
curl "https://tu-dominio.com/api/?action=socios&empresa=TELEFONICA"

# Análisis de gasto mensual
curl "https://tu-dominio.com/api/?action=resumen-gasto&periodo=mensual"

# Datos del Congreso (votaciones, Sankey, diputados)
curl "https://tu-dominio.com/api/?action=congreso"

# Promesas electorales (promesómetro, patrimonio, contradicciones)
curl "https://tu-dominio.com/api/?action=promesas"

💾 Almacenamiento de datos

Filosofía: Zero-Database

BOE Explorer usa almacenamiento flat-file JSON intencionalmente:

  • Sin dependencias — No necesita MySQL, PostgreSQL ni MongoDB
  • Portabilidad total — Los datos son archivos legibles por humanos
  • Backup trivialcp -r api/data/ backup/
  • Versionable — Compatible con git (aunque no recomendado por volumen)
  • Procesamiento incremental — Un archivo por día, merge selectivo

Estructura

api/data/
├── meta.json                     # Índice global: conteos diarios, rango de fechas, totales
├── boe/
│   └── YYYY-MM-DD.json           # Array de documentos BOE del día (~557 archivos)
├── bdns/
│   ├── convocatorias.json        # Todas las convocatorias (merge deduplicado por ID)
│   ├── taxonomias.json           # Datos de referencia (regiones, sectores, etc.)
│   └── meta.json                 # Metadata de actualización BDNS
├── borme/
│   ├── YYYY-MM-DD.json           # Actas parseadas de todas las provincias del día
│   ├── index.json                # Índice invertido empresa → fechas
│   └── meta.json                 # Metadata de procesamiento BORME
├── congreso/
│   ├── votaciones/               # 114 directorios de sesión
│   │   └── sesionNN/             # JSON por cada votación individual
│   ├── diputados.json            # Índice de diputados y grupos parlamentarios
│   ├── asistencia_cache.json     # Caché incremental de asistencia
│   └── meta.json                 # Metadata: 114 sesiones, 1666 votaciones
├── promesas/
│   └── promesas.json             # 34 promesas, 8 patrimonios, 7 contradicciones, keywords
└── .htaccess                     # "Deny from all" (seguridad)

Caché

api/cache/
├── {md5_hash}.json               # Cache con TTL configurable por endpoint
└── .htaccess                     # "Deny from all"
EndpointTTL
BOE día10 min
Dashboard5 min (rendered: 1h)
Licitaciones15 min
Analytics1 hora
Congreso30 min
Promesas1 hora

🚀 Instalación

Requisitos previos

  • PHP 8.0+ con extensiones: curl, json, mbstring, xml
  • pdftotext (poppler-utils) para parsing BORME
  • Servidor web con soporte PHP (Apache/Nginx)
  • ~500 MB de espacio en disco para datos históricos

Pasos

# 1. Clonar el repositorio
git clone https://github.com/vbmedina91/boeexplorer.git
cd boeexplorer

# 2. Instalar pdftotext (si no está instalado)
sudo apt-get install poppler-utils

# 3. Crear directorios de datos
mkdir -p api/data/boe api/data/bdns api/data/borme api/data/congreso api/data/promesas api/cache

# 4. Configurar permisos
chmod 755 api/data api/cache
chown -R www-data:www-data api/data api/cache

# 5. Proteger directorios de datos (si usas Apache)
echo "Deny from all" > api/data/.htaccess
echo "Deny from all" > api/cache/.htaccess

# 6. Ejecutar primera carga de datos
php cron_update.php

# 7. (Opcional) Backfill histórico — carga los últimos N días
php backfill.php --days=30

# 8. Abrir en el navegador
# http://tu-dominio.com/

Verificar instalación

# Comprobar estado del sistema
curl "http://tu-dominio.com/api/?action=status"

# Resultado esperado:
# {"version":"2.1.0","total_documentos":119000,...}

⏰ Configuración del cron

# Actualización diaria a las 20:00 (cuando BOE publica el sumario del día siguiente)
0 20 * * * cd /ruta/al/proyecto && php cron_update.php >> /var/log/boe_cron.log 2>&1

El cron ejecuta secuencialmente:

  1. Fetch BOE — Descarga sumario del día y clasifica documentos
  2. Enriquecimiento — Fetch XML individual de cada licitación para importes, adjudicatarios
  3. BDNS Update — Descarga nuevas convocatorias de subvenciones
  4. BORME Update — Descarga y parsea PDFs del Registro Mercantil
  5. Limpieza de caché — Invalida cachés afectados

🤝 Contribuir al proyecto

¡Las contribuciones son bienvenidas! BOE Explorer es un proyecto comunitario para mejorar la transparencia del Estado español.

¿Cómo puedes contribuir?

🐛 Reportar bugs

Abre un issue describiendo:

  • Qué esperabas vs qué ocurrió
  • Pasos para reproducir
  • Capturas de pantalla si aplica

💡 Proponer mejoras

Abre un issue con la etiqueta enhancement describiendo:

  • El problema que resuelve
  • Propuesta de solución
  • Impacto esperado

🔧 Contribuir código

  1. Fork del repositorio
  2. Crea una rama para tu feature: git checkout -b feature/mi-mejora
  3. Haz commit de tus cambios: git commit -m "Añadir: descripción"
  4. Push a tu fork: git push origin feature/mi-mejora
  5. Abre un Pull Request describiendo los cambios

📝 Mejorar documentación

  • Corregir errores en el README
  • Añadir ejemplos de uso de la API
  • Traducir a otros idiomas (inglés, catalán, etc.)

Áreas donde más se necesita ayuda

ÁreaDescripciónDificultad
Nuevos parsersParsear DOGC (Cataluña), BOJA (Andalucía), otros boletines autonómicosMedia-Alta
Machine LearningReemplazar clasificadores de keywords por modelos NLP (spaCy, BERT)Alta
Base de datosMigración opcional a SQLite/PostgreSQL para mejor rendimientoMedia
TestsCrear suite de tests unitarios (PHPUnit)Media
VisualizaciónNuevos tipos de gráficos, mapas interactivos de EspañaMedia
API públicaDocumentación OpenAPI/Swagger, rate limiting, API keysMedia
MobileApp React Native o PWA mejoradaAlta
AccesibilidadMejoras WCAG 2.1, navegación por tecladoBaja-Media
Internacionalizacióni18n para interfaz multilingüeBaja
Datos abiertosExportación CSV/Excel/JSON de resultadosBaja

Convenciones de código

  • PHP: Sin framework, código limpio y documentado con PHPDoc
  • JS: Vanilla ES2021+, funciones con nombres descriptivos
  • Commits: En español, formato Tipo: descripción (Añadir, Corregir, Mejorar, Refactor)
  • Sin dependencias externas (Composer/npm) — el proyecto funciona con git clone + PHP

🗺 Roadmap

✅ Completado

  • Congreso de los Diputados — Votaciones, Sankey, asistencia, correlación CCAA, buscador de diputados
  • Promesas Electorales — Promesómetro, nubes de palabras, timeline de contradicciones, patrimonio
  • Extracción de keywords desde PDFs — vía pdftotext sobre programas electorales
  • Cross-reference promesas ↔ BOE — Búsqueda automática de keywords en datos BOE existentes

🔜 Pendiente

  • Boletines autonómicos (DOGC, BOJA, BOCM, etc.)
  • Exportación de datos (CSV, Excel, JSON)
  • Mapas interactivos por CCAA con datos georreferenciados
  • Alertas personalizadas por email/Telegram
  • API pública con documentación Swagger
  • Tests unitarios y CI/CD
  • Migración opcional a SQLite para mejor rendimiento
  • PWA con soporte offline
  • Análisis de redes: grafos de relaciones empresa-departamento
  • Machine Learning para clasificación temática
  • Ampliar promesas a más partidos (ERC, PNV, Bildu, JxCAT)
  • Automatización completa de keywords con PDFs reales de programas

📄 Licencia

Este proyecto está bajo la licencia MIT. Ver LICENSE para más detalles.


🙏 Créditos


Hecho con ❤️ para la transparencia del Estado español
⭐ Dale una estrella si te resulta útil