feat(captacion_clientes): scraping freelance en perfil headless dedicado, no chromium-personal

El monitor de captación scrapeaba Workana sobre el navegador personal del
usuario (chromium-personal, CDP 9222), interfiriendo con su navegación. El
scraping CDP debe correr siempre en un perfil headless dedicado.

- Nuevo pipeline monitor_freelance_projects_headless: levanta un Chromium
  headless aislado con perfil dedicado (~/.config/fn_scrape_chrome, CDP 9334)
  vía systemd-run, ejecuta monitor_freelance_projects contra ese puerto y
  cierra la instancia al terminar (finally). Reutiliza el patrón de lifecycle
  de ingest_market_trends_headless. Reutiliza un CDP vivo si el puerto ya
  responde (no cierra lo ajeno).
- scrape_workana_projects y monitor_freelance_projects: default de `port`
  cambiado de 9222 (chromium-personal) a 9334 (perfil dedicado). Default seguro:
  correr a pelo sin Chrome en 9334 falla limpio, no contamina el 9222 personal.

Verificado: el wrapper arranca headless en 9334, scrapea 8 proyectos reales de
Workana, cierra la instancia (9334 muerto, sin proceso colgado) y deja el 9222
personal intacto.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-22 20:11:26 +02:00
parent c1f355ffa5
commit bcc1fe1738
6 changed files with 466 additions and 25 deletions
@@ -226,7 +226,7 @@ def monitor_freelance_projects(
upwork_query: str = "custom software",
duckdb_path: str = "",
xlsx_path: str = "",
port: int = 9222,
port: int = 9334,
timeout_s: float = 25.0,
) -> dict:
"""Detecta proyectos freelance nuevos, los persiste con dedup y exporta a Excel.
@@ -262,7 +262,10 @@ def monitor_freelance_projects(
xlsx_path: ruta del .xlsx de salida. Si "", usa
~/.fn_freelance/freelance_projects.xlsx (creando el directorio).
port: puerto de remote debugging del Chrome a usar por los scrapers.
Default 9222 (chromium-personal logueado).
Default 9334 (perfil headless dedicado del scraping). NUNCA 9222 por
defecto: ese es el chromium-personal del usuario. Para la corrida
programada usa el wrapper monitor_freelance_projects_headless, que
levanta el Chrome headless en 9334 y lo cierra al terminar.
timeout_s: timeout en segundos por pagina para los scrapers. Default 25.0.
Returns:
@@ -454,7 +457,7 @@ def main() -> int:
ap.add_argument("--upwork-query", default="custom software")
ap.add_argument("--duckdb-path", default="")
ap.add_argument("--xlsx-path", default="")
ap.add_argument("--port", type=int, default=9222)
ap.add_argument("--port", type=int, default=9334)
ap.add_argument("--timeout-s", type=float, default=25.0)
args = ap.parse_args()