feat(browser): auto-commit con 178 cambios
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
---
|
||||
name: detect_captcha
|
||||
kind: function
|
||||
lang: go
|
||||
domain: browser
|
||||
version: "1.0.0"
|
||||
purity: impure
|
||||
signature: "func DetectCaptcha(c *CDPConn) (detected bool, types []string, url string, err error)"
|
||||
description: "Detecta captchas y challenges anti-bot en la pagina actual via CDP: reCAPTCHA, hCaptcha, Cloudflare Turnstile (por iframe/widget) y el JS-challenge de Cloudflare (por texto). Solo detecta — no resuelve ni notifica. Una responsabilidad."
|
||||
tags: [captcha, browser, cdp, antibot, detection, perception]
|
||||
uses_functions: [cdp_evaluate_go_browser]
|
||||
uses_types: []
|
||||
returns: []
|
||||
returns_optional: false
|
||||
error_type: "error_go_core"
|
||||
imports: [encoding/json, fmt]
|
||||
params:
|
||||
- name: c
|
||||
desc: "Conexion CDP activa a una tab de Chrome de tipo 'page'. La evaluacion corre en el top frame."
|
||||
output: "Tupla (detected, types, url, err). detected=true si hay al menos una senal anti-bot. types es el subconjunto de senales detectadas (de: 'recaptcha', 'hcaptcha', 'turnstile', 'challenge'), siempre slice no nulo (vacio si nada). url es la location.href del top frame. err si la conexion es nula, falla el eval CDP, o el JSON resultante es invalido. Una excepcion JS en la pagina se trata como detected=false best-effort, sin error."
|
||||
tested: true
|
||||
tests: ["recaptcha detectado", "hcaptcha detectado", "turnstile detectado", "challenge por texto", "multiples senales", "ninguno", "campo error best-effort no rompe", "types ausente se normaliza a slice vacio", "json invalido devuelve error"]
|
||||
test_file_path: "functions/browser/detect_captcha_test.go"
|
||||
file_path: "functions/browser/detect_captcha.go"
|
||||
---
|
||||
|
||||
## Ejemplo
|
||||
|
||||
```go
|
||||
// Conectar a un Chrome con CDP abierto (mismo patron que cdp_get_text)
|
||||
conn, err := CdpConnect(9222)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer CdpDisconnect(conn)
|
||||
|
||||
// Tras navegar y esperar la carga, comprobar si la pagina puso un captcha
|
||||
detected, types, url, err := DetectCaptcha(conn)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
if detected {
|
||||
fmt.Printf("captcha detectado en %s: %v\n", url, types)
|
||||
// p.ej. -> "captcha detectado en https://x.test/login: [recaptcha]"
|
||||
} else {
|
||||
fmt.Println("sin captcha, seguir clicando")
|
||||
}
|
||||
```
|
||||
|
||||
## Cuando usarla
|
||||
|
||||
Tras navegar o esperar la carga de una pagina, para saber si esta puso un captcha o challenge anti-bot antes de seguir clicando o enviando formularios. La usa el `browser_mcp` en sus handlers de navegacion para decidir el handoff humano: si `DetectCaptcha` devuelve `detected=true`, el flujo automatico se detiene y avisa para resolucion manual en vez de chocar contra el muro.
|
||||
|
||||
## Gotchas
|
||||
|
||||
- **Solo top frame**: la evaluacion corre en el frame principal. Un captcha incrustado en un iframe anidado profundo cuyo `src` no matchee los patrones no se detecta.
|
||||
- **Iframes cross-origin**: el contenido de los iframes de reCAPTCHA/hCaptcha/Turnstile NO se lee (politica same-origin), pero SI se detectan por su `src` y por las clases del widget host (`.g-recaptcha`, `.h-captcha`, `.cf-turnstile`), que viven en el top document.
|
||||
- **Falsos positivos posibles**: la senal `challenge` viene de regex sobre `innerText` (p.ej. "verify you are human", "unusual traffic"). Una pagina con ese texto en otro contexto (un articulo, una FAQ sobre bots) puede dar `detected=true` sin haber captcha real.
|
||||
- **No detecta captchas custom**: solo cubre los proveedores listados (reCAPTCHA, hCaptcha, Turnstile) + el JS-challenge de Cloudflare. Captchas propios o de otros vendors no se reconocen.
|
||||
- **Depende de innerText**: la pagina debe haber pintado el body. En una tab aun cargando (`document.body` nulo o vacio) la senal `challenge` puede no dispararse — esperar con `cdp_wait_load` antes de detectar si el contenido es dinamico.
|
||||
- **Impura**: hace un round-trip CDP (I/O de red). Requiere conexion activa a una tab de tipo `page`.
|
||||
Reference in New Issue
Block a user