Volver a Proyectos

🎯 Soft-Scrappeo

CRM de captación de leads B2B: rastrea empresas, las enriquece y las reparte entre el equipo comercial

Desarrollado en empresa 4 versiones Roles admin / comercial

Escala del Proyecto

7.7kLíneas
4Versiones
2Roles
2026Prácticas

Descripción General

El equipo comercial de la empresa necesitaba una cosa muy concreta: dejar de buscar empresas a mano. Soft-Scrappeo automatiza ese trabajo — rastrea listados públicos, extrae los datos de cada empresa, los enriquece con información adicional y las clasifica por código CNAE, que es el estándar de actividad económica que usa el comercial para saber si un lead le encaja.

Pero un scraper suelto no resuelve el problema: los leads hay que repartirlos. Por eso el proyecto creció hasta ser un CRM completo con dos roles: el administrador ve el dashboard global y asigna leads, y cada comercial ve solo su cartera con la ficha detallada de cada empresa. Incluye chat interno y notificaciones.

Es el proyecto que desarrollé durante las prácticas de empresa del ciclo. Es el que más se parece a trabajar de verdad: requisitos que cambian sobre la marcha, usuarios reales usándolo mientras se desarrolla, y cuatro versiones en tres semanas.

Tecnologías Utilizadas


Python

Flask

SQLAlchemy

Web Scraping

Jinja2

Catálogo CNAE

Módulos del Sistema

🕷️ Scraper

scraper.py recorre los listados de origen y normaliza los datos de cada empresa.

✨ Enriquecimiento

enrichment.py completa la ficha con datos adicionales tras el primer rastreo.

🏷️ Catálogo CNAE

cnae_catalog.py clasifica cada empresa por su actividad económica oficial.

🧹 Saneado de leads

fix_leads.py corrige y deduplica registros del histórico.

📊 Dashboard admin

Vista global de la captación, con volumen y estado de los leads.

🤝 Asignaciones

El administrador reparte leads entre los comerciales del equipo.

📁 Cartera del comercial

Cada comercial ve solo sus leads, con ficha de detalle completa.

💬 Chat interno

Comunicación entre administrador y comerciales dentro de la herramienta.

🔔 Notificaciones

Avisos de asignación y de novedades sobre un lead.

👥 Usuarios

Gestión de cuentas y de su rol.

Arquitectura

Aplicación Flask clásica con plantillas Jinja2 y modelos SQLAlchemy. La separación importante no es por capas sino por rol: templates/admin/ y templates/comercial/ son dos interfaces distintas sobre los mismos datos, y una página 403.html dedicada cierra el paso a lo que no corresponde.

Soft-Scrappeo/V0.0.4/
├── app.py              # rutas y lógica de la aplicación
├── models.py           # modelos SQLAlchemy
├── config.py           # configuración
├── init_db.py          # creación del esquema
├── scraper.py          # rastreo de listados
├── enrichment.py       # enriquecimiento de fichas
├── cnae_catalog.py     # clasificación por actividad
├── fix_leads.py        # saneado del histórico
└── templates/
    ├── base.html · login.html · 403.html
    ├── chat.html · notificaciones.html
    ├── admin/           # dashboard, usuarios, asignaciones
    └── comercial/       # cartera y lead_detail

Evolución en 4 Versiones

Cada versión es una carpeta completa, lo que refleja cómo creció el encargo: empezó siendo un script con interfaz y acabó siendo un CRM con roles.

  • V0.0.1Primer prototipo: scraper con una interfaz mínima para lanzarlo y ver resultados.
  • V0.0.2Iteración sobre la interfaz y el volcado de datos.
  • V0.0.3-CRMEl salto: modelos SQLAlchemy, login, enriquecimiento y estructura de CRM.
  • V0.0.4Versión final: roles admin y comercial, asignaciones, catálogo CNAE, chat, notificaciones y saneado de leads.

Seguridad Implementada

  • Acceso con login y sesión; sin sesión no hay acceso a ninguna vista de datos.
  • Separación estricta por rol: el comercial no puede alcanzar las vistas de administración.
  • Página 403.html dedicada para los accesos no autorizados.
  • Configuración de credenciales y orígenes fuera del código, en config.py.
  • Consultas mediante el ORM de SQLAlchemy, sin SQL concatenado.

Retos Técnicos y Decisiones de Diseño

El scraping es la parte fácil; mantenerlo es la difícil

Un scraper funciona el día que se escribe y se rompe la semana siguiente. La estrategia fue separar rastreo de enriquecimiento: scraper.py solo captura lo mínimo fiable y enrichment.py completa después. Así un cambio en el origen degrada la calidad del dato pero no tumba el proceso, y el histórico se puede reparar con fix_leads.py sin volver a rastrear.

Clasificar por CNAE en lugar de por palabras clave

Al principio los leads se etiquetaban por texto libre, y el resultado era inservible para filtrar. Adoptar el catálogo CNAE — el código oficial de actividad económica — convirtió la clasificación en algo estándar y comparable: el comercial pide un sector y el sistema sabe exactamente qué devolver.

Dos interfaces, no una con condicionales

Tener admin y comercial en las mismas plantillas con if rol == por todas partes envenena el código y filtra información por descuido. Separar templates/admin/ y templates/comercial/ duplica algo de maquetación pero hace imposible que un comercial vea la vista global por accidente.

Mi Rol

Desarrollador en prácticas — autor del proyecto.

Recogí el requisito con el equipo comercial, propuse el enfoque y desarrollé las cuatro versiones: scraper, enriquecimiento, modelo de datos, sistema de roles, ambas interfaces y las utilidades de mantenimiento del histórico.

Estado del Proyecto

Entregado y usado por el equipo comercial de la empresa durante las prácticas (abril-mayo de 2026). La versión final es la V0.0.4.

Código y Enlaces

El código está en el repositorio TuaTeam, dentro de la carpeta Soft-Scrappeo/. Los datos de empresas rastreados no se incluyen.