feat(browser): funciones anti-deteccion + perfiles para web_scraping

Funciones nuevas del dominio browser (grupo navegator):
- cdp_move_mouse_human / cdp_click_human: movimiento de raton con curva
  de Bezier cubica, easing y micro-jitter para imitar comportamiento
  humano y reducir deteccion de automatizacion.
- cdp_wait_idle: espera network-idle contando requests en vuelo via
  eventos CDP Network.*; inmune a extensiones que mutan el DOM
  (Dark Reader, uBlock) y a animaciones JS.
- list_chrome_profiles: lista perfiles de un user-data-dir (extensiones,
  nombre legible, preferencias).
- prepare_chrome_profile (bash): clona un user-data-dir conservando solo
  una whitelist de extensiones (default uBlock Origin Lite).

Modificadas:
- chrome_launch: Linux-first (chromium/google-chrome/brave antes que
  chrome.exe), KeepExtensions y Setpgid para matar el arbol con cdp_close.
- cdp_close: kill por grupo de proceso.

Todas con tests verdes (go test ./functions/browser ok).
This commit is contained in:
Egutierrez
2026-06-05 16:25:11 +02:00
parent 729921e16e
commit ccfa5bc78b
17 changed files with 1603 additions and 45 deletions
+82
View File
@@ -0,0 +1,82 @@
---
name: cdp_move_mouse_human
kind: function
lang: go
domain: browser
version: "1.0.0"
purity: impure
signature: "func CdpMoveMouseHuman(c *CDPConn, toX, toY float64, opts MouseHumanOpts) error"
description: "Mueve el ratón desde (opts.FromX, opts.FromY) hasta (toX, toY) siguiendo una curva de Bézier cúbica con easing ease-in-out, micro-jitter perpendicular y pausas variables entre puntos, imitando el movimiento humano para reducir la detección de automatización."
tags: [cdp, chrome, browser, mouse, human, navegator]
uses_functions:
- cdp_evaluate_go_browser
uses_types: []
returns: []
returns_optional: false
error_type: "error_go_core"
imports:
- math
- math/rand
- time
tested: true
tests:
- "numero de puntos es steps+1"
- "primer punto aproxima origen"
- "ultimo punto aproxima destino"
- "todos los puntos dentro de bounding box razonable"
- "steps cero normaliza a 1 punto mas origen"
- "smoothstep en extremos es 0 y 1"
- "smoothstep monotono creciente"
- "curva de un solo segmento vertical"
- "defaults aplicados cuando opts es zero value"
- "valores explicitos no se sobreescriben"
- "puntos de control entre origen y destino (intervalo razonable)"
- "distancia cero no produce NaN"
test_file_path: "functions/browser/cdp_move_mouse_human_test.go"
file_path: "functions/browser/cdp_move_mouse_human.go"
params:
- name: c
desc: "Conexión CDP activa obtenida con CdpConnect."
- name: toX
desc: "Coordenada X del destino en píxeles de viewport."
- name: toY
desc: "Coordenada Y del destino en píxeles de viewport."
- name: opts
desc: "MouseHumanOpts: Steps (puntos intermedios, default 25), DurationMs (duración total, default 350-800 ms aleatorio), JitterPx (desviación perpendicular máxima por punto, default 2.0), FromX/FromY (origen, default 0,0 si < 0)."
output: "error si la conexión es nula o falla algún Input.dispatchMouseEvent."
---
## Ejemplo
```go
conn, _ := CdpConnect(9222)
defer CdpClose(conn, 0)
// Mover desde (100, 200) hasta (640, 480) con parámetros por defecto
err := CdpMoveMouseHuman(conn, 640, 480, MouseHumanOpts{
FromX: 100,
FromY: 200,
})
// Personalizar curva: 40 pasos, 600 ms, jitter de 4px
err = CdpMoveMouseHuman(conn, 300, 200, MouseHumanOpts{
Steps: 40,
DurationMs: 600,
JitterPx: 4.0,
FromX: 640,
FromY: 480,
})
```
## Cuando usarla
Antes de `CdpClick` o `CdpClickHuman` cuando necesitas que el movimiento del ratón parezca humano. Útil en scrapers o bots donde la trayectoria rectilínea instantánea dispara detección (Cloudflare, PerimeterX, DataDome). También útil para simular hover antes de un click para activar tooltips o menús desplegables.
## Gotchas
- Las coordenadas son relativas al viewport visible, no a la página completa. Si el elemento está fuera del scroll, las coordenadas serán incorrectas — hacer scroll primero con `CdpEvaluate` + `scrollIntoView`.
- `time.Sleep` es intencional: simula la duración física del movimiento. En tests headless sin Chrome real no hay efecto visible pero el sleep ocurre igualmente.
- No garantiza indetectabilidad total. Sistemas de detección sofisticados analizan más señales (aceleración del dispositivo, patrones de timing a lo largo de la sesión, huellas de Canvas/WebGL).
- `math/rand` usa la semilla por defecto (no criptográfica). Para movimientos más impredecibles, considera sembrar con `rand.New(rand.NewSource(time.Now().UnixNano()))`.
- El micro-jitter es perpendicular al segmento global origen-destino, no a la tangente local de la curva. Para trayectorias muy curvas, la dirección del jitter puede no ser óptima.
- `DurationMs` controla la pausa total pero no tiene en cuenta la latencia de red al Chrome. El movimiento real tarda `DurationMs + latencia_cdp * Steps`.