📡 Plataforma de Leads Inmobiliarios
Backend que rastrea portales inmobiliarios de Valencia, filtra por criterios de cliente y avisa en tiempo real
Escala del Proyecto
Descripción General
Una agencia inmobiliaria que quiere captar inmuebles tiene que revisar los portales cada día buscando novedades. Es trabajo mecánico, se hace mal y siempre se llega tarde: el que llama primero al propietario se lleva la captación.
Esta plataforma automatiza el ciclo completo. Un pipeline de ingesta programado por cron recorre los portales de Valencia, normaliza los datos y hace upsert de cada propiedad. Después un matcher cruza esas propiedades con los filtros de cada cliente — zona, precio, habitaciones, tipo — les asigna una puntuación y descarta las que no superan su umbral.
Lo que llega al cliente es un aviso por Telegram o WhatsApp solo con lo que le interesa, con una supresión de duplicados de 48 horas para no repetir el mismo inmueble. La V2 añade una capa de IA local con Ollama que analiza y prioriza los leads, y un bot conversacional para consultar la cartera por chat.
Tecnologías Utilizadas
TypeScript
Node.js
Express
node-cron
Cheerio
csv-parse
Zod
Telegram Bot API
Ollama
Arquitectura por Dominios
portalValenciaConservativeConnector.ts rastrea el portal real
con un enfoque deliberadamente prudente en frecuencia y volumen.
csvFeedConnector.ts ingiere un feed externo cuando el portal
bloquea el rastreo. Garantiza captación aunque falle la vía principal.
portalValenciaMockConnector.ts permite desarrollar y probar el
pipeline sin tocar el portal.
pipeline.ts orquesta el ciclo: ingesta, normalización y upsert
de propiedades.
matcher.ts cruza cada propiedad con los filtros del cliente y
calcula su puntuación.
storage.ts mantiene el estado de propiedades y leads, con
control de duplicados.
senders.ts envía por Telegram y por webhook de WhatsApp; ambos
opcionales según variables de entorno.
Bot conversacional de Telegram para consultar inmuebles por zona, precio y habitaciones.
Vista mínima en GET /app para inspeccionar el estado del
sistema.
En la V2, Ollama analiza los leads y los prioriza operativamente.
Arquitectura
Monorepo con la API en apps/api y el código dividido por dominio:
domain/ con los tipos, el almacenamiento y el matcher;
ingestion/ con el pipeline y los conectores; y
notifications/ con los emisores.
Los conectores comparten una interfaz común (connectors/types.ts), de
forma que añadir un portal nuevo no requiere tocar el pipeline. Es el punto donde la
arquitectura paga: cambiar de fuente es implementar una interfaz, no reescribir el
flujo.
Marketing/ ├── V1/ # implementación inicial └── V2/ # versión con IA local ├── data/ # valencia-feed-example.csv └── apps/api/ ├── src/server.ts ├── src/domain/ # types, storage, matcher ├── src/ingestion/ │ ├── pipeline.ts │ └── connectors/ # conservative, csvFeed, mock, types ├── src/notifications/ # senders.ts ├── scripts/ # production-check.mjs └── .env.example
Integraciones Externas
Notificación en tiempo real de cada lead que supera el umbral, y bot conversacional para consultar la cartera por zona, precio o habitaciones.
Vía alternativa de aviso, activable de forma independiente por variable de entorno.
Modelo de lenguaje ejecutado en local para el análisis operativo y la priorización de leads, sin enviar datos a terceros.
Programación del pipeline de ingesta con frecuencia configurable.
Flujo del Pipeline
- Disparo por cron: el scheduler lanza el ciclo de ingesta con la frecuencia configurada.
- Ingesta: el conector activo recorre el portal o el feed CSV y devuelve las propiedades encontradas.
- Validación: Zod verifica el esquema de cada registro y descarta lo que llega malformado.
- Normalización y upsert: los datos se homogeneizan y se insertan o actualizan en el almacenamiento.
- Matching: el matcher cruza cada propiedad con los filtros de cada cliente: zona, precio, habitaciones y tipo.
- Scoring: se calcula la puntuación del lead y se compara con el umbral mínimo del cliente.
- Supresión de duplicados: si ese inmueble ya se notificó en las últimas 48 horas, se descarta.
- Análisis con IA: en la V2, Ollama revisa los leads que pasan el filtro y ajusta su prioridad.
- Notificación: el lead se envía por Telegram y, si está activado, por el webhook de WhatsApp.
Retos Técnicos y Decisiones de Diseño
El scraping siempre se rompe: hay que asumirlo en el diseño
Depender de un único conector significa que el día que el portal cambie su HTML o bloquee el acceso, la captación se detiene. Por eso hay tres conectores tras la misma interfaz: el conservador contra el portal real, uno de feed CSV o API externa como respaldo, y uno mock para desarrollar. Cambiar de fuente es configuración, no reescritura.
Ser conservador a propósito
El conector principal se llama conservative por una razón: rastrear agresivamente consigue que te bloqueen la IP en una tarde. Limitar frecuencia y volumen reduce lo que capturas por ciclo, pero es la diferencia entre un sistema que funciona durante meses y uno que funciona un día.
Notificar poco para que se lea
Un sistema que avisa de todo se silencia a la semana. El valor está en el filtro: puntuación con umbral configurable por cliente y cooldown de 48 horas por inmueble. La métrica de éxito no es cuántos leads envías, es que el cliente siga abriendo los avisos al mes siguiente.
IA local en lugar de una API de pago
Analizar cada lead con un servicio en la nube sería un coste variable por cada inmueble rastreado, y enviaría datos de propietarios a un tercero. Ollama corriendo en la misma máquina hace el coste fijo y mantiene los datos dentro.
Mi Rol
Desarrollador backend — autor único.
Diseño del pipeline, los tres conectores, el matcher con scoring, la supresión de duplicados, los emisores de notificación, el bot de Telegram y la integración de Ollama en la V2.
Estado del Proyecto
Dos versiones funcionales. La V2 es la actual e incorpora la capa
de IA local y el bot conversacional. Incluye production-check.mjs para
validar la configuración antes de desplegar.
Código y Enlaces
Las variables sensibles (token del bot, chat ID, clave de la API de ingesta y URL
del portal objetivo) viven en .env y nunca se suben al repositorio.