Este proyecto implementa un pipeline de datos robusto para la ingesta, procesamiento y modelado de las licitaciones publicadas en la Plataforma de Contratación del Sector Público (PLACSP).
Originalmente desarrollado con lxml y SQLite (disponible ahora en la carpeta lxml_SQLite/), el sistema ha evolucionado hacia una arquitectura de Data Lakehouse moderna y escalable.
- Procesamiento: Apache Spark (PySpark), Pandas
- Almacenamiento: Delta Lake / Parquet
- Orquestación: Apache Airflow
- Configuración: YAML (para esquemas y reglas de transformación)
- Gestión de Entorno: Pixi
El proyecto extiende el patrón estándar de Medallion Architecture con una capa Raw explícita, resultando en cuatro capas. Consulta docs/architecture.md para el razonamiento completo.
- Raw (Immutable): Zona de descarga. Almacena los ficheros originales XML/ATOM, el Excel de Órganos de Contratación y los archivos
.gcdel repositorio CODICE sin ninguna modificación. Ninguna otra capa escribe aquí.- Bash Scripts: Para la descarga masiva de históricos y la obtención del directorio oficial de Órganos de Contratación.
- Python (
requests): Para la descarga de archivos.gcdel repositorio CODICE araw/data/gc_codes/. - Python (lxml): Para la descarga incremental diaria con watermarking por dataset.
- Bronze (Extraction): Extracción estructural. Los ficheros XML/ATOM de Raw se parsean con
spark-xmly se convierten en tablas Delta planas. Los archivos.gcderaw/data/gc_codes/se parsean conlxmly se consolidan enbronze/data/gc_codes.parquet. Los códigos GC permanecen como URIs técnicas sin traducir.- Dead Letter Pattern para registros XML corruptos (
bronze/data/dead_letters/). - Dual-read (
rowTag="entry"+rowTag="at:deleted-entry") para granularidad de fallo a nivel de entry individual.
- Dead Letter Pattern para registros XML corruptos (
- Silver (Trusted/Enriched):
- Traducción semántica: Sustitución de URIs de códigos GC por descripciones legibles mediante Broadcast Joins contra
bronze/data/gc_codes.parquet. - Trazabilidad Temporal (SCD Tipo 2): Hereda la
sk_idMD5 generada en Bronze y la usa para el seguimiento histórico de versiones de cada expediente. - Gestión Dimensional: Tabla de Órganos de Contratación con evolución de esquema dinámica (
autoMerge) en Delta Lake. - Modelado denormalizado con
StructsyArraysde Spark.
- Traducción semántica: Sustitución de URIs de códigos GC por descripciones legibles mediante Broadcast Joins contra
- Gold (Analytics): Data Marts específicos orientados a negocio. Actualmente se incluye un mart filtrado para el sector de Mobiliario de Oficina en la zona Levante/Centro.
- Integridad Referencial por Hashing: Uso de MD5 para generar claves subrogadas estructurales (
sk_id) en Bronze (32 caracteres), vinculando entidades derivadas (lots,documents,results) conentriesdesde la extracción, y habilitando SCD Tipo 2 en Silver sin recalcular la clave. - Transformación Basada en Esquemas: Sistema sistemático de limpieza y casteo automático basado en definiciones lógicas (fechas, divisas, emails, importes, etc.).
- Optimización de JOINs: Uso de funciones de orden superior (
transform) para procesar arrays internos y lógica condicional para evitar "structs fantasma" llenos de nulos. - Idempotencia y Schema Evolution: El pipeline está diseñado para ser re-ejecutable mediante operaciones
MERGE(UPSERT) que asimilan de forma inteligente nuevas columnas agregadas por diferentes fuentes (ej. Streaming XML vs. Base Excel). - Resiliencia ante Datos Corruptos (Dead Letter Pattern): Los entries ATOM que no pueden ser parseados se desvían automáticamente a una tabla Delta de dead letters (
bronze/data/dead_letters/) en lugar de interrumpir el pipeline. El mecanismo usa una lectura dual (rowTag="entry"+rowTag="at:deleted-entry") concolumnNameOfCorruptRecordhabilitado en ambas, garantizando granularidad de fallo a nivel de entry individual, trazabilidad completa y replayabilidad.
El proyecto se organiza en cuatro capas (arquitectura Medallion extendida). Consulta docs/architecture.md para la descripción completa de cada capa y su justificación.
- Capa Raw (Inmutable):
raw/data/: Almacenamiento inmutable de ficheros originales (XML/ATOM, XLSX,.gc). Histórico enraw/data/{year}/{dataset_name}/, descargas diarias enraw/data/daily/{dataset_name}/, archivos Genericode enraw/data/gc_codes/.raw/scripts/download_placsp.sh: Descarga masiva del histórico de todos los datasets.raw/scripts/download_parties.sh: Descarga del fichero Excel oficial de Órganos de Contratación.raw/scripts/download_gc_codes.py: Descarga de archivos.gcdel repositorio CODICE araw/data/gc_codes/.raw/scripts/daily_download.py: Descarga incremental diaria. Calcula watermark por dataset consultando la capa Bronze con DuckDB.
- Capa Bronze (Extracción Estructural):
bronze/src/: Código fuente de PySpark: esquemas (schema.py), funciones de extracción (extraction.py), Dead Letter (dead_letter.py) y utilidades (utils.py).bronze/scripts/extract_biddings.py: Extracción histórica por año (batch). Lee deraw/data/y escribe enbronze/data/.bronze/scripts/daily_extraction.py: Extracción incremental mediante Structured Streaming. Lee deraw/data/daily/con un stream independiente por dataset.bronze/scripts/extract_parties.py: Actualiza la dimensión de Órganos de Contratación desde el Excel de Raw.bronze/scripts/extract_gc_codes.py: Lee los archivos.gcderaw/data/gc_codes/y generabronze/data/gc_codes.parquet.bronze/notebooks/: Cuadernos de exploración y prototipado Spark.bronze/data/: Tablas Delta extraídas (entries,lots,documents,results,parties),dead_letters/,gc_codes.parquetycheckpoints/.bronze/schema_def.yml: Definición centralizada de tipos y reglas de limpieza (usada por Silver).
- Capa Silver (Enriquecimiento Semántico):
silver/src/utils.py: Funciones de traducción de catálogos GC via Broadcast Join:load_catalog_df(),replace_code_description()(escalar),replace_code_description_list()(array de strings),replace_code_description_struct()(array de structs).silver/src/parties_cleanup.py: Funciones de limpieza para la dimensión de Órganos de Contratación:clean_administrative_code(),clean_free_text(),clean_parent_level(),clean_email(),clean_phone(),clean_cities(),clean_postal_code().silver/scripts/cleanup_biddings.py: ETL de licitaciones. Lee Bronzeentries, aplica las transformaciones documentadas endocs/cleanup_biddings.mdy produce dos tablas Delta:entries(193,885 filas activas, con códigos GC traducidos, fechas corregidas y arrays normalizados) ydeleted_entries(694 entradas anuladas con columnassk_id,id,updated,deleted_comment_type).silver/scripts/cleanup_parties.py: ETL de Órganos de Contratación. Lee Bronzepartiesy produce la dimensión Silver limpia ensilver/data/parties/.silver/notebooks/biddings_exploration.ipynb: Exploración columna a columna de la tablaentries. Documenta cobertura, distribución, anomalías y prototipa la transformación Silver de cada campo. Referencia:docs/cleanup_biddings.md.silver/notebooks/contracting_parties_exploration.ipynb: Exploración y prototipado de transformaciones para la dimensiónparties.silver/data/2026/licitaciones/entries/: Tabla Delta Silver de licitaciones activas.silver/data/2026/licitaciones/deleted/: Tabla Delta Silver de entradas anuladas.silver/data/parties/: Tabla Delta Silver de Órganos de Contratación.
- Capa Gold (Analytics):
gold/: (En desarrollo) Modelos dimensionales y tablas agregadas para consumo final.
- Legacy (v1.0):
lxml_SQLite/: Implementación original basada en SQLite, incluyendo su propio código fuente y esquemas.
- Documentación y Recursos:
docs/architecture.md: Descripción completa de la arquitectura de 4 capas y su justificación.docs/tables/: Diccionarios de datos por entidad y Diagrama Entidad-Relación (diagram.md).docs/: Artículos técnicos sobre Claves Subrogadas, Gestión de Genericodes, Órganos de Contratación, Dead Letter Pattern y Exploración y Limpieza de Licitaciones Silver.examples/: Archivos de ejemplo para pruebas rápidas.
Para más detalles sobre la arquitectura y el estándar de datos:
docs/architecture.md: Arquitectura de 4 capas (Raw, Bronze, Silver, Gold) y justificación de las decisiones de diseño.docs/resumen_PLACSP.md: Guía de parseo y mapeo estructural del estándar CODICE.docs/tables/diagram.md: Modelo lógico de datos y relaciones entre entidades.
Todos los datos de la PLACSP se encuentran en https://www.hacienda.gob.es/es-ES/GobiernoAbierto/Datos%20Abiertos/Paginas/licitaciones_plataforma_contratacion.aspx.
Más informacion en docs/PLACSP Conjunto de datos
- Licitaciones publicadas en los perfiles del contratante ubicados en la Plataforma de Contratación del Sector Público, excluyendo los contratos menores.
- Licitaciones publicadas en la Plataforma mediante mecanismos de agregación, excluyendo los contratos menores
- Contratos menores publicados en los perfiles del contratante ubicados en la Plataforma de Contratación del Sector Público
- Encargos a medios propios publicados en los perfiles de contratante ubicados en la plataforma de contratación del sector público
- Consultas preliminares de mercado publicadas en los perfiles de contratante ubicados en la plataforma de contratación del sector público
- Organos de contratación