Ir al contenido principal

Todos los datos de Córdoba en un solo lugar (y sobre un CKAN diferente)

Hay un portal nuevo de datos abiertos de Córdoba: cbadatos.com.ar. No es oficial, es una iniciativa personal. Reúne en un solo lugar lo que publican los portales de la provincia, de algunos municipios, de la Legislatura y de la UNC: hoy son 1.935 conjuntos de datos de once fuentes distintas. En este post van dos historias: cómo se juntaron tan rápido todos esos datos y el experimento técnico que corre por debajo, un CKAN que funciona sin Solr ni Redis.

Portada de Córdoba Datos

Parte 1: todos los datos de Córdoba en un solo lugar

Harvesting: la parte fácil

CKAN tiene desde hace años un mecanismo para cosechar (harvest) datos de otros portales. Si el portal de origen también es CKAN, traer todo su catálogo es casi trivial: se configura la URL, se elige cada cuánto actualizar y listo. CKAN habla con CKAN a través de su API y trae datasets, recursos, organizaciones y metadatos.

Eso fue lo que pasó con los dos portales de la provincia que migramos este año, datosgestionabierta.cba.gov.ar y datosestadistica.cba.gov.ar (lo conté en este post), con el portal de datos abiertos de la UNC que también hicimos desde cero y con el portal de Río Tercero. Cuatro portales CKAN, más de mil conjuntos de datos, en muy poco tiempo. Es lo que pasa cuando los portales usan software libre y estándares abiertos: se pueden conectar entre ellos muy facilmente.

Fuentes de importación de Córdoba Datos

Le agregamos al cosechador de CKAN dos cosas que nos parecían importantes:

  • Copiar los archivos, no solo los enlaces. Cada archivo se descarga una vez, de a uno y con pausas para no molestar al portal de origen. Así el sitio sirve también como respaldo: si un dato desaparece del portal original, acá sigue.
  • Que cada dato diga de dónde viene. Cada conjunto de datos guarda el portal de origen, el enlace al original y la organización que lo produjo. Las organizaciones de cada portal quedan separadas para que no se mezclen datos de fuentes distintas.

Los portales que no son CKAN

La parte difícil fueron los que no usan CKAN. Para cada uno hubo que escribir un cosechador personalizado:

Todos se actualizan solos, la mayoría una vez por semana.

El gran portal que falta

Hay uno que todavía no está: el portal de transparencia de la Provincia de Córdoba, el que (entre otras cosas) publica cada comprobante de pago del Estado provincial. Es probablemente el conjunto de datos más valioso de la provincia y también el más difícil de usar. Tenemos esos datos disponible en un portal cerrado hecho con la Red Ruido, todavía no esta listo para compartir, lo conté en este post.

Portada de Presupuesto Abierto

Por qué juntar todo

Los datos de Córdoba existen pero están distribuidos en muchos lugares distintos, cada uno con su buscador, su formato y su forma de organizar las cosas.

Conjuntos de datos por portal de origen

Tenerlos en un solo lugar cambia la pregunta: ya no es "¿dónde está este dato?" sino "¿qué hay sobre este tema?". Un buscador sobre todo, filtros por portal de origen, por organización, por formato, 166 grupos temáticos. Y una sola API para todo lo de la provincia, que es algo que ningún organismo por sí solo puede ofrecer.

Un conjunto de datos de la UNC con su procedencia

Además todos los datos tabulares se cargan al datastore de CKAN, así que se pueden consultar por API, ver como tabla y filtrar sin descargar nada. Los datos geográficos de IDECOR (muchos, son 627 conjuntos de datos) se ven en un mapa.

Barrios de Villa Allende, desde IDECOR

Todo el código del portal es público: parripollo/ckanext-cordoba-portal. Ahí están los cosechadores de cada fuente, por si alguien quiere reutilizarlos en otro lado.

Parte 2: un CKAN sin Solr ni Redis

Si entrás a la página "Sobre este CKAN" vas a ver que este portal no corre sobre el CKAN oficial.

Sobre este CKAN y este experimento

El problema

Un sitio CKAN son tres servicios: PostgreSQL para el catálogo, Apache Solr para las búsquedas y Redis para las tareas en segundo plano. Cada uno hay que instalarlo, monitorearlo y actualizarlo en sintonía con la versión de CKAN. Para un portal chico o mediano (que son casi todos) es mucha infraestructura alrededor de lo que al final es una aplicación Python sobre una base de datos.

Simplificar CKAN no es un problema nuevo, se ha discutido muchas veces pero el desafió es muy grande.

El experimento

Así que lo intentamos. La propuesta está documentada en ckan.cbadatos.com.ar y el código es público en parripollo/ckanito. La idea es que CKAN sea para los datos abiertos lo que Django es para las aplicaciones web: instalar, apuntar a una base de datos y correr.

CKAN on PostgreSQL only

En resumen:

  • La búsqueda (texto completo, facetas, filtros y orden) corre sobre el full text search de PostgreSQL.
  • Las tareas en segundo plano son filas en una tabla que los workers toman con SELECT ... FOR UPDATE SKIP LOCKED.
  • Las sesiones y un pequeño almacén clave/valor para extensiones también viven en PostgreSQL.
  • Cada una de esas piezas quedó detrás de una interfaz. Si alguien quiere volver a usar Solr o Redis (vade retro!) puede escribir su implementación en una extensión sin tocar el núcleo. Nosotros (?) solo hicimos la de PostgreSQL. Creo que el error original de CKAN no fue usar Solr y Redis sino hablar con ellos desde todos lados, sin un contrato que se pueda reemplazar.
  • La API pública, las interfaces de plugins y la línea de comandos son las mismas. Pasan todos los tests de CKAN (unos 3.500), los linters y la construcción de la documentación.
  • Las extensiones se probaron una por una. La mayoría funcionaron sin cambios o con cambios mínimos. Harvest y spatial necesitaron un backend nuevo.

Todos los cambios están juntos en un solo pull request contra un fork de CKAN, que existe solo para poder leer la diferencia: 107 archivos, unas 4.000 líneas agregadas y otras tantas borradas. La mayor parte de lo que se borra es Solr.

El pull request: Solr y Redis afuera

Hay mucho para seguir revisando. El trabajo fue mayormente hecho por IA (Claude, Fable 5). Nosotros dirigimos el trabajo y tomamos las decisiones. Claude (el modelo de Anthropic) hizo el trabajo técnico: leyó el código de CKAN, propuso alternativas, escribió el código, los tests y la documentación. parripollo es la cuenta de GitHub que le dimos para trabajar aislado. Los tests de CKAN fueron el árbitro en cada paso.

Trabajo con CKAN hace años. Aun así, no puedo decir que entiendo al 100% cada una de las miles de líneas que cambiaron. Puedo leerlas, puedo ver que los tests pasan, puedo ver dos portales funcionando con miles de datos reales. Pero no las escribí yo, y entender un cambio así de profundo en CKAN requiere mucho más que leerlo.

Y al mismo tiempo el resultado es real: un portal de datos que se instala con PostgreSQL y un par de comandos. Si esto funciona bien, levantar un portal de datos abiertos para un municipio chico, una universidad o una organización deja de requerir tres servicios y alguien que sepa mantenerlos.

¿Y ahora?

No tengo una respuesta y me gustaría dejar el debate abierto:

  • ¿Tiene sentido proponer esto a la comunidad de CKAN? ¿Alguien va a querer revisar miles de líneas escritas mayormente por una IA?
  • ¿Es razonable usarlo en portales de verdad? Hoy lo usa cbadatos, que es un experimento ciudadano. ¿Lo pondríamos en un portal de gobierno?
  • ¿Quién lo mantiene? CKAN sigue avanzando y cada cambio del CKAN oficial hay que traerlo a esta versión.
  • ¿Cuánto tengo que entender de un código para confiar en él? ¿Alcanza con los tests, con verlo funcionando, con que otras personas lo revisen?

Presupuesto Abierto: seis años de scraping y un portal para periodistas

En mayo de 2020 consolidé una serie de scripts que venían procesando (desde hacía algunos años y con otros investigadores) la ejecución presupuestaria de la Provincia de Córdoba desde su portal de transparencia. Seis años después eso es FreeData: un portal con más de seis millones de comprobantes de pago, de 2016 a 2026, y más de medio millón de proveedores. Esta semana Ruido, la red de periodismo de investigación con la que trabajamos, lo presentó públicamente.

Portada de Presupuesto Abierto

El origen del dato

La Provincia publica cada comprobante que paga. Eso es mucho más de lo que publica la mayoría de los gobiernos argentinos y es bueno reconocerlo. El problema es cómo: un portal donde para llegar a un comprobante hay que elegir el año, después la jurisdicción, después el programa, el subprograma, la partida, y recién ahí aparece una lista paginada de a diez. No hay descarga, no hay API, no hay forma de preguntar "cuánto cobró este CUIT".

Portal de transparencia de la Provincia de Córdoba

Lo que hice fue recorrer ese árbol completo, año por año, nodo por nodo, guardando cada comprobante con sus items. Es scraping paciente: millones de pedidos durante alrededor de una decada, muchos reintentos y una base que crece de a poco. En 2026 la Provincia cambió el portal y hubo que reescribir todo el recolector contra la interfaz nueva.

El portal

Sobre esa base construimos desde cero una aplicación en Django con PostgreSQL. Lo principal:

  • Búsqueda por proveedor, CUIT, programa o partida, en toda la serie.
  • Montos originales y actualizados por inflación (gracias Sol Monoldo!), mes a mes, para que una compra de 2017 se pueda comparar con una de 2026.
  • Tiempos de cobro por proveedor: cuánto tarda el Estado en pagarle a cada uno.
  • Seguimiento: cualquier usuario puede seguir un proveedor y recibir avisos cuando aparecen comprobantes nuevos.
  • Notas de usuarios sobre proveedores, para que un periodista le ponga nombre conocido a una razón social.
  • Descarga en CSV de cualquier búsqueda, con los filtros aplicados.
  • Graficos, muchos gráficos por todos lados.
  • Descargas de CSV de tablas a la vista para seguir trabajando en la compu o cruzar datos por fuera.

Ficha de un proveedor en Presupuesto Abierto

Portal privado

Este es un portal cerrado. Se entra por invitación y con passkeys. Hoy lo usan periodistas y de a poco se va abriendo a investigadores y organizaciones.

¿Por qué?

La decisión de no abrirlo tiene varias razones (no necesariamente en este orden):

  • Alojar esta cantidad de datos y todas las posibilidad que da esta plataforma en un servidor require recursos que este proyecto no tiene. Nada de esto genera ingresos de ninguna forma lamentablemente. Hemos postulado a subsidios pero todavía no hemos tenido suerte. Acá podes donar a la Red Ruido
  • El trabajo realizado es muy grande, requiere validación que todo funcione como se espera. Estamos en etapa de pruebas.
  • Hay datos que consideramos que no es buena idea que sean públicos. Asumimos que los responsables de este portal son plenamente concientes de lo que publican pero aunque parezca extraño no coincidimos con semejante nivel de apertura. Sin dar ejemplos, hay datos que se refieren a situaciones personales de las personas que si bien como fondos publicos deben ser abiertos no es buena idea que se publiquen de forma indiscriminada. Por eso el portal es privado y con invitación a personas que lo van a usar responsablemente con fines perdiosticos y de investigación.
  • Porque si, porque despues de tanto trabajo esta bien ser discrecionales con el uso. Queremos que esto se use bien.

Algo de cocina

  • Django y PostgreSQL, sin frameworks de frontend. HTML plano y algo de JavaScript donde hace falta.
  • Dos servidores chicos: uno con un webserver y la aplicación detrás de Cloudflare y otro con la base de datos.
  • Cache, mucho cache en cada lugar que se pudo.
  • El recolector corre aparte: cada año tiene un porcentaje de cobertura que se controla con un informe de integridad para saber que falta
  • Autenticación con WebAuthn. Nadie tiene una contraseña que filtrar.
  • Respeto por el servidor del que obtenemos datos. Corremos muy lento, en general entre 20 y 40 requests por minuto.

Riesgos

En 2026 la Provincia cambió la interfaz gráfica y escondió muchos datos. Saco tambien las Agencias de Gobierno (Cultura, Deportes, etc). Muchos subprogramas ya no son visibles. ¿Que pasa si se apaga el portal? Esta plataforma puede seguir abierta aún si eso pasara y hoy mismo ya muestra más datos que el portal oficial por lo que se escodió en la última actualización.

Migrar dos portales de datos abiertos después de una década sin actualizar

Terminamos la migración de los dos portales de datos abiertos de la Provincia de Córdoba: datosgestionabierta.cba.gov.ar y datosestadistica.cba.gov.ar. Fue un año de trabajo, desde agosto de 2025 hasta agosto de 2026. Lo cuento porque es el tipo de proyecto que casi nunca se cuenta: no hay nada nuevo para inaugurar, hay algo viejo que dejó de ser un riesgo.

Portal de datos abiertos de la Provincia de Córdoba

El punto de partida

Los dos portales corrían sobre CKAN 2.6.2 con PostgreSQL 9.6, en servidores propios del gobierno. Esa versión de CKAN es de 2017. Nadie la había actualizado en casi diez años. Funcionaban pero cada día que pasaba la brecha con el CKAN actual se hacía más grande y el salto más caro.

Los que trabajamos con CKAN sabemos que una actualización de 2.6 a 2.11 no es una actualización menor. Cambió Python (de 2 a 3), cambió el framework web (de Pylons a Flask), cambió el esquema de la base y cambió la forma de escribir extensiones. Lo que había que hacer era construir portales nuevos y mover los datos.

Dos herramientas libres

Decidimos que todo lo que no fuera específico de Córdoba quedara publicado. Salieron dos repositorios:

ckan-to-aws despliega CKAN completo en AWS con Terraform y Docker: una tarea de ECS Fargate con CKAN, Solr y Redis, una base RDS PostgreSQL, imágenes en ECR, secretos en Secrets Manager y logs en CloudWatch. Un script, un .env y ya tenemos un CKAN andando.

ckan-migrator hace la migración a nivel base de datos. Levanta el dump viejo en un PostgreSQL 9.6 dockerizado, extrae cada tabla a CSV y JSON, y las inserta en el CKAN nuevo respetando el esquema actual. Datasets, recursos, organizaciones, grupos, usuarios y el historial de actividad. Los archivos subidos se mueven aparte.

Lo que sí es específico de Córdoba quedó en repositorios privados, uno por portal: una extensión para la interfaz de cada uno (los dos portales pertenecen a ministerios distintos y tienen identidad propia) y la configuración de cada ambiente. Cada equipo del gobierno tiene su repo y puede gestionar sus diferencias sin tocar la base común.

Portal de la Dirección de Estadísticas y Censos

Conjuntos de datos del portal

Lo que queda

Todo el proceso fue documentado exaustivamente para que cualquier equipo técnico pueda actualizar CKAN en el futuro sin depender de un proveedor externo. La migración de datos es reproducible y los portales pueden ser desplegados en cualquier nube o servidor propio.