Spain Public Procurement Tenders (PLACSP) avatar

Spain Public Procurement Tenders (PLACSP)

Pricing

from $6.00 / 1,000 results

Go to Apify Store
Spain Public Procurement Tenders (PLACSP)

Spain Public Procurement Tenders (PLACSP)

Daily structured export of Spanish government tenders from PLACSP, filtered to your sector by CPV code: buyer, amount, deadline and direct link.

Pricing

from $6.00 / 1,000 results

Rating

0.0

(0)

Developer

Bluewither

Bluewither

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

8 days ago

Last modified

Categories

Share

placsp-licitaciones

Actor de Apify que lee el feed oficial de datos abiertos de la Plataforma de Contratación del Sector Público (PLACSP) y devuelve, por cada licitación: objeto del contrato, importe, organismo, CPV, plazos y enlace.

Pensado como plantilla reutilizable para los siguientes actors del mismo molde (bundle de portales de empleo, reemplazo del scraper de Instagram, etc.): la separación feedClient.js (red + paginación) / parser.js (XML → JSON) / main.js (orquestación + Apify SDK) / monitor/ (vigilancia propia) es el patrón a copiar.

Estado actual (2026-08-11)

  • ✅ Estructura del feed investigada contra datos reales (no documentación de terceros): capturado y verificado un feed real con Chrome, incluyendo un ejemplo completo de licitación, una baja (at:deleted-entry), y las listas oficiales de códigos de estado y de tipo de procedimiento.
  • ✅ Parser y normalización implementados y probados (npm test, 5/5 OK) contra una fixture montada con datos reales capturados.
  • ✅ Actor completo (src/main.js) probado de punta a punta en local: lee input, calcula "hoy" en Europe/Madrid correctamente, y maneja errores guardando una señal en el key-value store (ESTADO_MONITOR) para el monitor propio.
  • Desplegado y probado con ejecuciones reales en Apify (actor bluewither/my-actor) — ver "Resultado de las ejecuciones reales" abajo. No hubo ningún bloqueo de IP/WAF: la teoría inicial de riesgo de bloqueo (que aparecía en esta sección antes de hoy) quedó descartada.
  • ✅ Monitor propio (monitor/check-run.mjs) y workflow de GitHub Actions listos para desplegar; pendiente de activar con las credenciales reales.
  • ✅ Ficha de tienda y precio en STORE_LISTING.md, revisada con datos reales de volumen (no solo estimación).

✅ Resultado de las ejecuciones reales en Apify (2026-08-11)

El actor se desplegó manualmente en Apify (Console Web IDE) y se lanzaron dos runs de prueba contra el feed real de PLACSP, para el día 2026-08-10:

  1. Feed completo, sin filtro: build correcta (42 s, $0.009) y run correcta (1 min 12 s, $0.019) con 2138 licitaciones extraídas y normalizadas correctamente, recorriendo 5 páginas del feed. Cero errores, cero bloqueos 403/429.
  2. Filtrado por cpvPrefijos: ["72"] (servicios informáticos), mismo día: run correcta (1 min 8 s, $0.009) con 114 licitaciones — un 5,3% del total nacional, confirmando que el filtro por sector reduce el volumen al orden de magnitud esperado (decenas/bajos cientos, no miles).

Conclusión sobre el riesgo de bloqueo por IP/WAF (la preocupación original de este documento): la infraestructura de Apify no tiene ningún problema para leer el feed público de PLACSP. Los 403 Forbidden observados en sesiones de desarrollo anteriores venían de la lista blanca de salida de red del entorno de desarrollo en la nube usado para construir este actor (que solo permite npm/PyPI/GitHub/Anthropic), no de un WAF de PLACSP bloqueando datacenters en general. No hace falta PlaywrightCrawler ni proxy de pago: el fetch simple con cabeceras de navegador (src/feedClient.js) funciona tal cual en producción.

Hallazgo aparte, ya resuelto: el volumen real (2138/día a nivel nacional) es ~14 veces mayor que la estimación de partida usada para fijar el precio (~150/día), lo que habría hecho el precio por licitación inviable para el caso de uso de "toda España cada día". Solución adoptada: reposicionar el actor en torno al filtrado por CPV/sector (ver STORE_LISTING.md), donde el volumen real por cliente (114/día para un sector como TI) sí encaja con el precio propuesto.

Estructura del proyecto

.actor/actor.json Metadatos del actor para Apify
.actor/input_schema.json Formulario de input (fecha, filtros, límite páginas)
Dockerfile Imagen del actor (apify/actor-node:20)
src/config.js Mapeos de códigos oficiales (estado, procedimiento) y cabeceras
src/parser.js XML del feed -> objetos normalizados
src/feedClient.js Descarga + paginación + filtrado por fecha
src/main.js Orquestación: input -> feed -> dataset + monitor
monitor/check-run.mjs Monitor propio (independiente de Apify), para cron externo
.github/workflows/monitor.yml Ejemplo de cómo programar el monitor gratis en GitHub Actions
test/parser.test.js Tests con datos reales capturados (npm test)
test/sample-feed.atom Fixture: página real de PLACSP + 2 casos sintéticos de borde
STORE_LISTING.md Propuesta de título, descripción y precio para la tienda

Campos que devuelve cada licitación

expediente, objetoContrato, organismo, jerarquiaOrganismo (cadena de organismos padre), nifOrganismo, importe (estimado, totalConImpuestos, totalSinImpuestos, moneda), cpv (array de códigos), estadoCodigo/estado, procedimientoCodigo/procedimiento, ubicacion, plazo (fechaLimite, horaLimite), enlace, perfilContratanteUrl, idExpedienteFeed, uuidTed, fechaActualizacionFeed, anulada.

Cómo probarlo

npm install
npm test # tests del parser contra datos reales capturados
node src/main.js # ejecución completa (necesita salida a internet real)

node src/main.js en el entorno de desarrollo en la nube usado para construir este actor fallará con BloqueoAntiBotError — es la lista blanca de salida de red de ese entorno, no un bloqueo real de PLACSP (ver "Resultado de las ejecuciones reales" arriba). Pruébalo desde tu propio ordenador o, mejor, directamente en Apify, donde funciona sin problema.

Input

Ver .actor/input_schema.json. Por defecto: fecha de hoy (Europe/Madrid), incluye anuladas, sin filtro de CPV, hasta 200 páginas del feed.

Siguientes pasos (en orden)

  1. Declarar la actividad a Compliance del banco antes de facturar nada (cuenta de Apify ya creada y actor ya desplegado y probado).
  2. Desplegar este actor y lanzar un run de prueba real ✅ hecho (2026-08-11): 2138 licitaciones sin filtro, 114 filtrando por CPV 72, sin bloqueos.
  3. Si hace falta, cambiar a PlaywrightCrawler no hace falta: el fetch simple funciona en Apify tal cual.
  4. Publicar en la Store con el texto de STORE_LISTING.md (ya revisado con datos reales de volumen y reposicionado en torno al filtrado por CPV).
  5. Programar el run diario en Apify + el monitor (monitor/check-run.mjs) en GitHub Actions, con margen antes de la hora estimada del test de Apify.
  6. Con la plantilla ya probada, replicar para el bundle de empleo y, en último lugar, el reemplazo del scraper de Instagram.