Scraping
Yozh Scraper procesa cualquier URL en un navegador real de Playwright y devuelve exactamente lo que pidas: campos extraídos, HTML sin procesar o una captura de pantalla de la página completa. Cada extracción es una tarea asíncrona: envía una URL, consulta el estado de la tarea y obtén el resultado. Los proxies, el modo sigiloso, los ajustes predefinidos y las sesiones autenticadas son todos de primera clase.
- Representación real del navegador: Playwright representa páginas creadas con JavaScript; desactiva
renderdesactivar para HTML estático. - Extracción estructurada: las reglas de campos CSS o XPath devuelven un
data, mucho más económico que descargar y analizar el HTML sin procesar por tu cuenta. - Proxies integrados: CyberYozh residencial / LTE móvil / centro de datos, con segmentación geográfica y sin búsqueda de ID de grupo.
- Modo sigiloso por defecto: parches «playwright-stealth» (
navigator.webdriver, huella digital de WebGL/Canvas, tiempo de ejecución de Chrome) para reducir la detección de bots. - Configuraciones predefinidas: extrae datos de Amazon, Google, eBay, Walmart, YouTube y LinkedIn por nombre, con autocorrección opcional mediante LLM.
- Sesiones: sesiones autenticadas gestionadas por el servidor para los objetivos que han iniciado sesión, que se reutilizan en los rastreos.
:8001) recorre un sitio web partiendo de una URL inicial y extrae todas las páginas mediante este rastreador; las mismas funciones de renderizado, proxy y sesión se aplican a las páginas rastreadas.Inicio rápido
El scraper sale desde la raíz docker-compose.yml (junto al crawler):
cp .env.example .env # set CYBERYOZH_API_KEY if using proxies docker compose up --build # scraper → http://localhost:8000 # crawler → http://localhost:8001
Comprueba que esté activo:
curl http://localhost:8000/api/v1/health
# {"status":"ok","workers":2}
CYBERYOZH_API_KEY en .env (puedes conseguir una en app.cyberyozh.com/api-access). Sin ella, solo proxy_type: none funciona.Uso básico
Cada punto final de scraping crea una tarea en segundo plano y devuelve un job_id. Consulta el estado del trabajo y, a continuación, recupera sus resultados.
curl -X POST http://localhost:8000/api/v1/scrape/page
-H "Content-Type: application/json"
-d '{ "url": "https://example.com", "proxy_type": "none" }'
# → { "job_id": "req_abc123" }
curl http://localhost:8000/api/v1/scrape/req_abc123 # status
curl http://localhost:8000/api/v1/scrape/req_abc123/results # results
El resultado final incluye metadatos y todo lo que hayas solicitado (data, raw_html, screenshot_base64):
{
"job_id": "req_abc123",
"status": "done",
"total": 1, "done": 1,
"results": [
{
"request_id": "req_abc123",
"took_ms": 1234,
"meta": { "url": "https://example.com", "final_url": "https://example.com/",
"status_code": 200, "device": "desktop", "proxy_type": "none", "retries": 0 },
"data": null, "raw_html": null, "screenshot_base64": null, "warnings": []
}
]
}
status movimientos queued → running → done (o failed / cancelled). Los resultados están disponibles para done, failedy cancelled puestos de trabajo.Extraer datos
Aplicar una extract regla y la respuesta incluirá un data objeto con claves que son los nombres de tus campos — mucho más sencillo que descargar raw_html y analizarlo tú mismo. Las reglas son css o xpath.
curl -X POST http://localhost:8000/api/v1/scrape/page
-H "Content-Type: application/json"
-d '{
"url": "https://example.com",
"extract": {
"type": "css",
"fields": {
"title": { "selector": "h1", "attr": "text", "required": true }
}
}
}'
# result → { "data": { "title": "Example Domain" } }
Cada campo es una regla:
| Clave de campo | Tipo | Por defecto | Descripción |
|---|---|---|---|
selector | string | obligatorio | Selector CSS o expresión XPath para el campo. |
attr | string | text | Qué leer — text o un nombre de atributo (p. ej., href, src). |
all | bool | false | Devuelve todos los resultados como una lista, en lugar de solo el primero. |
required | bool | false | Se señala cuando falta: activa la autorreparación preconfigurada del LLM. |
Utiliza "type": "xpath" con selectores XPath (p. ej., //h1) para la misma forma.
Capturas de pantalla y código HTML sin formato
Establecer screenshot: true para un PNG a página completa (base64 en screenshot_base64), o raw_html: true para obtener el código HTML completo tras el renderizado en raw_html.
curl -X POST http://localhost:8000/api/v1/scrape/page
-H "Content-Type: application/json"
-d '{ "url": "https://example.com", "screenshot": true, "raw_html": true }'
block_assets, desactívalo para las capturas de pantalla para que se muestren las imágenes.Proxies
Para realizar un scraping fiable, los proxies son imprescindibles, ya que la mayoría de los sitios web modernos bloquean las solicitudes directas. Yozh se integra con el servicio de proxies CyberYozh; configura proxy_type en cualquier solicitud.
| proxy_type | Qué es |
|---|---|
res_rotating | Rotación residencial: opción predeterminada recomendada. |
res_static | Estática residencial (IP dedicada). |
mobile | Móvil / LTE, dedicado. |
mobile_shared | Móvil / LTE, fondo común. |
dc_static | Estática del centro de datos. |
none | Conexión directa, sin proxy. |
Selecciona una ubicación con proxy_geo (country_code / region / city). Descubre lo que has comprado sin tener que buscar los identificadores de los grupos:
curl "http://localhost:8000/api/v1/proxies/available?proxy_type=res_rotating" curl "http://localhost:8000/api/v1/proxies/countries"
CYBERYOZH_API_KEY en el scraper .env. Consigue uno en app.cyberyozh.com/api-access, y, a continuación, reinicia el contenedor.Presets
Un ajuste preestablecido combina un perfil de solicitud, una plantilla de URL y una receta de análisis, lo que te permite extraer datos de un sitio web por su nombre en lugar de tener que crear manualmente una solicitud. Se incluyen ajustes preestablecidos para Amazon, Google, eBay, Walmart, YouTube y LinkedIn; también puedes crear los tuyos propios (mediante CSS/XPath determinista o generados por IA).
curl -X POST http://localhost:8000/api/v1/scrape/preset/page
-H "Content-Type: application/json"
-d '{
"source": "amazon_product",
"preset_params": { "asin": "B08N5WRWNW" },
"locale": "us",
"llm": { "model": "openai/gpt-5.4-mini" }
}'
# → { "job_id": "..." } then GET /api/v1/scrape/<job_id>/results
llm es opcional. Sin él, el analizador determinista se ejecuta por sí solo; con él, los selectores se reparan automáticamente cuando un required campo devuelve un valor vacío. Las claves del proveedor (OPENAI_API_KEY / ANTHROPIC_API_KEY / GEMINI_API_KEY / OPENROUTER_API_KEY) se encuentran en el lado del servidor en .env.Gestiona los ajustes predefinidos a través de GET /api/v1/presets, GET /api/v1/presets/{name}, y POST /api/v1/presets (los nombres de los ajustes predefinidos de usuario deben empezar por user_).
Sesiones
Sesiones autenticadas gestionadas por el servidor: se crea una, se inicia sesión una vez y, a continuación, se pasa su session_id a cualquier rastreo para que las páginas se recuperen con las cookies almacenadas y el estado de almacenamiento. Es necesario para objetivos que requieren inicio de sesión, como el linkedin_profile preajuste.
POST /api/v1/sessions— create. Pinesdevice/proxy_type/proxy_geoy un TTL. Devuelve{ session_id, expires_at }.POST /api/v1/sessions/{id}/login— reproducir un script de inicio de sesión declarativo concredsen el cuerpo:{ script, creds }.POST /api/v1/scrape/pageconsession_idset — scrape autenticado.DELETE /api/v1/sessions/{id}— limpiar.
# 1. create → {"session_id":"sess_...","expires_at":...}
curl -X POST http://localhost:8000/api/v1/sessions
-H "Content-Type: application/json"
-d '{ "device": "desktop", "proxy_type": "res_rotating" }'
# 2. log in (declarative DSL + creds)
curl -X POST http://localhost:8000/api/v1/sessions/sess_.../login
-H "Content-Type: application/json"
-d '{ "script": { "steps": [ {"op":"goto","url":"https://site/login"} ] },
"creds": { "username": "...", "password": "..." } }'
# 3. scrape with the session
curl -X POST http://localhost:8000/api/v1/scrape/page
-H "Content-Type: application/json"
-d '{ "url": "https://site/secure", "session_id": "sess_...", "raw_html": true }'
session_id y cookies juntos → 422. El contenido extraído device / proxy_type / proxy_pool_id / proxy_geo deben coincidir con los valores fijos de la sesión. En el caso de CAPTCHA o 2FA, si el DSL de inicio de sesión no puede resolverlo, omite el script e inyecta cookies en la sesión en su lugar.Extracción por lotes
Envía varias páginas en un solo trabajo con POST /api/v1/scrape/pages — cada entrada es una solicitud de rastreo completa. Consulta el estado y obtén los resultados a través de los mismos puntos de acceso del trabajo.
curl -X POST http://localhost:8000/api/v1/scrape/pages
-H "Content-Type: application/json"
-d '{
"pages": [
{ "url": "https://example.com", "proxy_type": "none" },
{ "url": "https://example.org", "proxy_type": "none" }
]
}'
session_id se aplica a todas las páginas del lote (se rechaza con un 422 si una página ya tiene fijado otro).MCP
El scraper aloja un punto final del Protocolo de Contexto de Modelo en /mcp (HTTP con capacidad de transmisión). Sitúa el cursor o el puntero sobre él y las herramientas aparecerán automáticamente:
run_scrape_pagerun_scrape_pagesget_job_statusget_job_resultcancel_scrape_jobhealth
"yozh-scraper": {
"type": "http",
"url": "http://localhost:8000/mcp"
}
Entonces solo tienes que pedir: «Extrae el contenido de https://example.com y dime qué hay en la página». El mismo punto final funciona tanto desde un agente de LangChain como desde un nodo de la herramienta cliente MCP de n8n.
Referencia de configuración
Solicitud — ScrapeRequest (seleccionado)
| Campo | Tipo | Por defecto | Descripción |
|---|---|---|---|
url | cadena (URL) | obligatorio | La página que hay que mostrar y de la que hay que extraer datos. |
render | bool | true | Generar con el navegador (necesario para páginas creadas con JavaScript). |
wait_until | domcontentloaded · networkidle | domcontentloaded | Cuando la página se considera lista. |
wait_for_selector | cadena · nulo | null | Espera a que aparezca un elemento concreto antes de capturar la imagen. |
device | desktop · mobile | desktop | Ventana de visualización / Perfil de agente de usuario. |
proxy_type | Véase «Proxies» | none | Conjunto de servidores proxy por los que pasan las rutas de recuperación. |
proxy_geo | ProxyGeo · nulo | null | Segmentación por país, región o ciudad. |
session_id | cadena · nulo | null | Utiliza una sesión autenticada; consulta la sección «Sesiones». |
stealth | bool | true | Aplica medidas de refuerzo contra la detección. |
block_assets | bool · null | env | Bloquear imágenes, fuentes y archivos multimedia para mejorar la velocidad (se recurre a BLOCK_ASSETS). |
extract | ExtractRule · nulo | null | Reglas de campo CSS/XPath → estructuradas data. |
raw_html | bool | false | Incluye el código HTML completo tras el renderizado. |
screenshot | bool | false | Captura un archivo PNG a página completa (base64). |
Referencia de la API
| Método | Ruta | Propósito |
|---|---|---|
| POST | /api/v1/scrape/page | Extrae una página. Devuelve {"job_id":"…"}. |
| POST | /api/v1/scrape/pages | Extrae varias páginas de forma masiva en un solo proceso. |
| POST | /api/v1/scrape/preset/page | Extraer datos por nombre de configuración preestablecida (Amazon, Google, …). |
| GET | /api/v1/scrape/{id} | Estado del trabajo (en cola/en ejecución/finalizado/…). |
| GET | /api/v1/scrape/{id}/results | Resultados del trabajo (páginas + ScrapeResponse). |
| DELETE | /api/v1/scrape/{id} | Cancelación suave: finalización de las páginas durante el vuelo. |
| POST | /api/v1/sessions | Crea una sesión autenticada. |
| POST | /api/v1/sessions/{id}/login | Ejecuta un script de inicio de sesión declarativo. |
| DELETE | /api/v1/sessions/{id} | Eliminar una sesión. |
| GET | /api/v1/proxies/available | Mostrar los proxies comprados de un tipo determinado. |
| GET | /api/v1/presets | Lista de preajustes integrados y de usuario. |
| GET | /api/v1/health | Salud + número de trabajadores. |
Detalles importantes
CYBERYOZH_API_KEY en el scraper .env. Sin ella, solo proxy_type: none funcionará la conexión (directa).session_id y cookies devuelve un 422, y el scraping debe coincidir con los valores fijados de la sesión device / proxy_type / proxy_geo.OPENAI / ANTHROPIC / GEMINI / OPENROUTER) procedentes de .env — que el cliente nunca envía.