JobBot es un pipeline asíncrono de prospección B2B y contacto automatizado. Utiliza técnicas de dorking a nivel nacional para recolección de objetivos, scraping con evasión de firewalls (WAFs) para extraer datos de contacto, y un motor SMTP/WhatsApp que compila y envía currículums hiper-personalizados al vuelo.
JobBot nace de una necesidad real y de la frustración con el ecosistema actual de reclutamiento. Después de meses de enviar solicitudes a través de portales tradicionales (ZonaJobs, Randstad, Bumeran, LinkedIn) con tasas de respuesta bajísimas, decidí cambiar la estrategia y volver a lo básico: entregar el CV directamente en la puerta de la empresa. Pero en lugar de hacerlo a pie una tarde de lluvia, decidí automatizarlo.
Al buscar herramientas de automatización de Cold Emailing u OSINT en GitHub, me encontré con un problema: casi todos los repositorios actuales son simples "wrappers" que requieren tarjetas de crédito para pagar costosas APIs de IA generativa (OpenAI, Claude) solo para leer un HTML básico.
Por eso construí JobBot bajo una filosofía técnica estricta:
- Determinismo sobre Alucinación: El bot no utiliza LLMs para tareas de clasificación. Emplea un motor léxico propio en Python puro con expresiones regulares para decidir el score del prospecto sin equivocarse.
- Evasión Stealth: Supera protecciones como Cloudflare o Datadome utilizando
playwright-stealth, rotación de contextos, spoofing de zona horaria y simulación de biometría humana (movimientos de mouse y scroll aleatorio). - CVs Mutantes (Typst): En lugar de enviar un PDF genérico, el orquestador lee la web de la empresa e inyecta las keywords exactas de la compañía en plantillas Typst por perfil (
CV_Tech,CV_Admin_IT,CV_Hybrid), compilando un PDF único antes de enviarlo. - Daemon 24/7 Resiliente: Diseñado para correr de fondo en
tmux. Cuenta con manejo seguro de señales de apagado (SIGTERM), timeouts estrictos anti-livelock y pausas aleatorias (Jitter) para evitar baneos de IP o de cuenta SMTP.
- Pipeline Producer-Consumer: Arquitectura asíncrona con
asyncio.Queuepara dorking y scraping concurrente con semáforos, resolviendo deadlocks mediante SENTINEL patterns yconsumer_readyevents. - Dorking Engine Nacional: Automatiza consultas avanzadas leyendo listas de rubros dinámicas desde un archivo externo (
rubros.txt). - 3 Perfiles de CV Dinámicos: Asignación automática de plantilla según el scoring:
CV_Tech(software, pentesting, full-stack),CV_Admin_IT(AFIP, POS, oficina, soporte),CV_Hybrid(operaciones + infraestructura IT). - 12×12 Email Templates: 12 asuntos y 12 cuerpos con tonos variados (formal, conversacional, directo, storytelling, problem-solving) para evitar detección como correo automatizado.
- Rich TUI (Terminal User Interface): Un panel de control y telemetría inspirado en la estética retro-futurista de Teenage Engineering, con mascota animada por estado.
- Módulo WhatsApp Web: Despacho automatizado de mensajes de presentación a líneas celulares extraídas de la web, con sesiones persistentes y rate-limits adaptables.
- Smart Dispatcher (SMTP): Cliente de correo con soporte para Dry-Run, jitter anti-ban y colas asíncronas.
- Lead Scoring con Señales Negativas: Motor léxico que excluye portales de noticias, blogs y e-commerce B2C antes de evaluar contactos, con trazabilidad de penalizaciones.
jobbot/
├── pyproject.toml # Metadata, dependencias, entry points
├── .env.example # Plantilla de variables de entorno
├── rubros.txt # Sectores industriales (uno por línea)
├── roadmap.md # Hoja de ruta del producto
├── README.md
├── src/
│ └── jobbot/
│ ├── __init__.py # Paquete raíz, versión
│ ├── __main__.py # python -m jobbot
│ ├── cli.py # Argparse, validación, entry point
│ ├── config.py # Variables de entorno centralizadas
│ ├── core/
│ │ └── orchestrator.py # Pipelines, estado, TUI loop
│ ├── cv/
│ │ ├── builder.py # Compilación Typst asíncrona
│ │ ├── profiles.py # 3 perfiles con datos reales del CV
│ │ └── templates/
│ │ ├── cv_tech.typ # Plantilla: Software & Security
│ │ ├── cv_admin_it.typ # Plantilla: Admin, Ops & IT Support
│ │ └── cv_hybrid.typ # Plantilla: Operaciones IT híbridas
│ ├── db/
│ │ ├── manager.py # SQLite WAL, migraciones, CRUD
│ │ ├── models.py # Dataclasses (Empresa, Contacto, Envio)
│ │ └── queries.py # SQL queries extraídas
│ ├── outreach/
│ │ ├── mailer.py # Motor SMTP con CV dinámico
│ │ ├── wa_sender.py # Motor WhatsApp Web
│ │ └── templates.py # 12 asuntos × 12 cuerpos × firma
│ ├── scoring/
│ │ └── engine.py # Scoring léxico + señales negativas
│ ├── scraper/
│ │ ├── engine.py # Playwright stealth, procesar_dominio
│ │ ├── stealth.py # Contextos aislados, resource blocking
│ │ └── navigation.py # Navegación deep, priority paths
│ ├── tui/
│ │ ├── dashboard.py # Paneles Rich, telemetría
│ │ ├── mascot.py # Mascota 8-bit animada
│ │ └── state.py # BotState, EstadoBot
│ └── utils/
│ ├── browser.py # apply_stealth()
│ ├── phone.py # Extracción de números WhatsApp
│ ├── domain.py # Validación y extracción de dominios
│ └── stealth.min.js # JS injection antibot
├── tests/
│ ├── test_scoring.py
│ ├── test_cv_builder.py
│ ├── test_db.py
│ └── test_outreach_templates.py
└── cvs/
├── template.typ # Plantilla Typst legacy (fallback)
└── perfil.jpg # Foto de perfil para el CV
git clone https://github.com/alaska45l/jobbot.git
cd jobbot
python -m venv .venv
source .venv/bin/activate# Producción
pip install -e .
# Desarrollo (incluye pytest)
pip install -e '.[dev]'
# Playwright necesita sus navegadores
playwright install chromiumCopiar la plantilla y completar con tus credenciales:
cp .env.example .env# Servidor SMTP (Recomendado: Gmail con App Password)
SMTP_HOST="smtp.gmail.com"
SMTP_PORT="587"
SMTP_USER="tu_correo@gmail.com"
SMTP_PASS="tu_app_password_de_16_caracteres"
# Perfil del Remitente
SENDER_NAME="Tu Nombre"
GITHUB_USER="TuUsuarioGitHub"
LINKEDIN_USER="TuUsuarioLinkedIn"-
Typst: Se requiere el binario de Typst en el
PATHpara la compilación dinámica de CVs.# Opción 1: Cargo cargo install typst-cli # Opción 2: Binario precompilado # https://github.com/typst/typst/releases # Verificar typst --version
-
Plantillas CV: Las plantillas por perfil viven en
src/jobbot/cv/templates/. La imagen de perfil es opcional encvs/perfil.jpg.
El sistema se opera mediante el CLI jobbot (instalado via pip install -e .) o python -m jobbot.
Ejecuta el ciclo completo (Dork → Scrape → Mail) en un loop infinito con manejo de timeouts y descansos anti-ban.
jobbot --auto --concurrencia 3Fase 1: Recolección de Semillas (Dorking)
jobbot --dork --rubros-file rubros.txt --limite-dork 30Fase 2: Extracción y Scoring (Scraping)
jobbot --scrape --concurrencia 3Fase 2b: Dork + Scrape en paralelo (Producer-Consumer)
jobbot --dork-scrape --concurrencia 2Fase 3: Despacho (Mailing o WhatsApp)
# Auditoría en terminal (Dry-Run: No acciona envíos reales)
jobbot --mail --dry-run --min-score 55
jobbot --wa --dry-run
# Ejecución real
jobbot --mail --min-score 55
jobbot --waEl scoring engine asigna automáticamente uno de 3 perfiles al compilar el CV para cada empresa:
| Perfil | Cuándo se asigna | Foco del CV |
|---|---|---|
CV_Tech |
Software houses, consultoras IT, ciberseguridad | Go, Rust, SvelteKit, pentesting, INVARIANT SYSTEM, CI/CD |
CV_Admin_IT |
Clínicas, estudios, inmobiliarias, PyMEs sin equipo dev | AFIP, POS Morphi, stock, soporte HW/SW, Excel, Windows Server |
CV_Hybrid |
Logística, manufactura, empresas medianas con depto. de sistemas | Operaciones + IT, Python automation, redes, soporte + admin |
El perfil CV_Hybrid se activa cuando el scoring detecta que una empresa cruza señales tech y admin simultáneamente (≥2 keywords de cada uno), o cuando dominan keywords operacionales-IT como "logística", "sucursales", "ERP", "mesa de ayuda".
Toda la metadata se almacena en jobbot.db (SQLite, WAL mode). Para reiniciar métricas, liberar el cooldown de 90 días o realizar un borrado:
-- Limpiar historial de envíos (reinicia el cooldown de SMTP)
DELETE FROM campanas_envios;
-- Wipe total (Borrar inteligencia recolectada)
DELETE FROM contactos;
DELETE FROM empresas;# Instalar dependencias de desarrollo
pip install -e '.[dev]'
# Ejecutar test suite
pytest -q
# Solo py_compile (sin pytest)
python -m py_compile src/jobbot/cli.py src/jobbot/scoring/engine.py| Argumento | Tipo | Default | Descripción |
|---|---|---|---|
--auto |
Flag | — | Inicia el Daemon de ejecución continua 24/7. |
--dork |
Flag | — | Solo dorking (semillas a DB, sin scraping). |
--scrape |
Flag | — | Solo scraping (dominios pendientes desde DB). |
--dork-scrape |
Flag | — | Dork + Scrape en paralelo (Producer-Consumer). |
--mail |
Flag | — | Ejecuta el motor SMTP con Typst. |
--wa |
Flag | — | Ejecuta el motor de envíos por WhatsApp Web. |
--rubros-file |
String | rubros.txt |
Archivo txt con la lista dinámica de rubros. |
--limite-dork |
Int | 30 |
Número máximo de resultados por rubro. |
--concurrencia |
Int | 2 |
Instancias Playwright en paralelo (máx 10). |
--min-score |
Int | 55 |
Puntaje mínimo para envío automático. |
--dry-run |
Flag | — | Simula el envío sin accionar SMTP/WA. |
--limite |
Int | 10 |
Límite de empresas a procesar. |
--headless |
Flag | — | Forzar modo headless en Playwright. |
--forzar-rescraping |
Flag | — | Ignorar cooldown de scraping. |
Nota: Los modos (
--auto,--dork,--scrape,--dork-scrape,--wa) son mutuamente excluyentes.
| Capa | Tecnología |
|---|---|
| Lenguaje | Python 3.11+ |
| Async | asyncio (Producer-Consumer, Queue, Event, semáforos) |
| Browser | Playwright (Chromium, headless, stealth contexts) |
| Base de datos | SQLite3 (WAL, STRICT tables, foreign keys) |
| CV Compiler | Typst CLI (binario externo, 3 plantillas .typ) |
smtplib + email.message.EmailMessage |
|
Playwright con user_data_dir persistente |
|
| TUI | Rich (Live, Layout, Panel, mascota animada) |
| Env | python-dotenv |
| Search | ddgs (DuckDuckGo search) |