
Aloísio Vítor
Image Processing Expert

AntiCloudflareTask con un proxy estático o pegajoso.El monitoreo confiable de inventario en comercio electrónico es un problema de evidencia, no solo un problema de obtención de páginas. Una página de producto puede mostrar "en stock" mientras que un tamaño específico esté agotado, una API de mercado puede estar rezagada respecto a un feed de comerciante, y un desafío de Cloudflare puede reemplazar la página esperada con una respuesta intersticial. El flujo correcto es primero API, consciente de variantes y consistente en sesión. Utiliza feeds oficiales cuando estén disponibles, registra observaciones estructuradas de stock y activa CapSolver solo cuando un desafío de Cloudflare de soporte interrumpa un flujo de navegador autorizado. Esta guía explica el modelo de datos, el flujo de recuperación de desafíos, los requisitos de proxy estático y agente de usuario, el intercambio de cookies, la detección de cambios en inventario, los controles de alerta y los límites de cumplimiento para operaciones de retail, inteligencia de catálogo y monitoreo de disponibilidad aprobado.
El monitoreo de inventario debe responder una pregunta operativa específica. Ejemplos comunes incluyen:
Evite un objetivo vago como "monitorear este producto". Defina el identificador del producto, variante, región, contexto de entrega, fuente y condición de alerta.
inventory_job = {
"canonical_product_id": "catalog-7821",
"gtin": "0099999999999",
"variant": {
"color": "negro",
"tamaño": "M",
},
"market": "US",
"destination_postal_code": "94107",
"sources": [
"merchant_inventory_feed",
"marketplace_api",
"authorized_product_page",
],
"alert_on": ["OUT_OF_STOCK_TO_IN_STOCK"],
}
El blog de comercio de CapSolver https://www.capsolver.com/blog/ecommerce cubre flujos de comercio relacionados, y la FAQ de scraping web de CapSolver explica consideraciones operativas para la recolección de datos públicos permitidos.
Las fuentes oficiales suelen ser más estables y fáciles de auditar. Utilice feeds de comerciantes, APIs de vendedores, puntos finales de inventario de mercados y proveedores de catálogos licenciados antes de leer páginas orientadas al comprador.
La documentación del API de búsqueda de eBay admite búsquedas de artículos por palabra clave, categoría, ePID, GTIN, condición y otros filtros. Para tiendas que publican páginas de producto estructuradas, Schema.org Offer define campos como availability, price, priceCurrency, seller y cantidad elegible. La documentación de datos estructurados de producto de Google explica cómo los datos de oferta y disponibilidad pueden aparecer en la marcación de producto.
| Fuente | Rol recomendado | Fortaleza principal | Limitación principal |
|---|---|---|---|
| Alimento de inventario del comerciante | Primario para catálogo propio | Datos directos de SKU y cantidad | Limitado a su relación comercial |
| API de mercado | Primario para listados de mercado aprobados | Identificadores y filtros estructurados | Cuotas y campos específicos del mercado |
| Proveedor licenciado | Normalización transmercado | Esquema consistente | Costo de licencia y cobertura |
| Página pública autorizada | Validación y cobertura de brechas | Refleja el estado orientado al comprador | Cambios en el diseño y validación de tráfico |
La recolección del navegador debe validar o complementar una brecha de datos conocida, no reemplazar una fuente oficial disponible.
Un campo genérico in_stock: true no es suficiente. Preservar variante, canal, mercado, vendedor y evidencia.
from dataclasses import dataclass, field
from datetime import datetime, timezone
@dataclass
class InventoryObservation:
source: str
canonical_product_id: str
source_item_id: str | None
gtin: str | None
variant: dict[str, str]
market: str
seller_id: str | None
availability: str
quantity: int | None
quantity_confidence: str
delivery_method: str | None
store_id: str | None
source_url: str | None
evidence: dict
parser_version: str
observed_at: str = field(
default_factory=lambda: datetime.now(timezone.utc).isoformat()
)
Utilice un vocabulario controlado para la disponibilidad:
VALID_AVAILABILITY = {
"IN_STOCK",
"OUT_OF_STOCK",
"PREORDER",
"BACKORDER",
"LIMITED",
"UNKNOWN",
}
Si la página dice solo "disponible", registre la cantidad como None. No infiera un valor numérico.
La guía de datos web con Python de CapSolver proporciona contexto de implementación, mientras que el glosario de CapSolver puede ayudar a los equipos a estandarizar términos.
El analizador debe verificar la identidad de la página antes de leer los datos de stock. Una página de desafío puede devolver HTTP 200 y aún así no contener elementos de producto esperados.
CHALLENGE_TITLES = {
"just a moment...",
"attention required!",
}
async def classify_page(page) -> str:
title = (await page.title()).strip().lower()
html = (await page.content()).lower()
if title in CHALLENGE_TITLES:
return "CLOUDFLARE_CHALLENGE"
if "cf-chl-" in html or "challenge-platform" in html:
return "CLOUDFLARE_CHALLENGE"
if await page.locator('[data-product-id]').count():
return "PRODUCT_PAGE"
return "UNKNOWN_PAGE"
Trate estos marcadores como señales de enrutamiento, no como prueba universal. Mantenga fixtures específicos del objetivo y pruébelos contra páginas autorizadas para acceder.
El producto de página de Cloudflare de CapSolver describe la tarea de desafío soportada, y el blog de Cloudflare de CapSolver contiene contexto de solución de problemas.
La documentación oficial de desafío de Cloudflare de CapSolver define AntiCloudflareTask.
| Campo | Requerido | Uso en monitoreo de inventario |
|---|---|---|
type |
Sí | Fijo como AntiCloudflareTask |
websiteURL |
Sí | URL exacta aprobada de producto o lista |
proxy |
Sí | Proxy estático o pegajoso utilizado por el navegador |
userAgent |
No | Agente de usuario de Chrome soportado exacto del navegador |
html |
No | HTML intersticial reciente cuando sea necesario |
La solución puede incluir una cookie cf_clearance, token y agente de usuario. Estos valores son material de sesión de corta duración. Deben ser consumidos por el entorno de monitoreo, no almacenados en un almacén de análisis.
La documentación de desafíos de Cloudflare de Cloudflare explica el propósito y tipos de mecanismos de desafío. La capacidad técnica no otorga permiso de acceso, por lo tanto, la política de fuente sigue siendo la regla controladora.
No exponga credenciales de proxy a un analista, modelo, registro o alerta. Resuelva un perfil dentro de código confiable.
import os
from urllib.parse import urlparse
import capsolver
capsolver.api_key = os.environ["CAPSOLVER_API_KEY"]
SOURCE_POLICY = {
"shop.example.com": {
"proxy_profile": "inventory_us_west",
"max_checks_per_hour": 4,
}
}
PROXY_VAULT = {
"inventory_us_west": os.environ["INVENTORY_PROXY_US_WEST"],
}
def approved_host(url: str) -> str:
host = urlparse(url).hostname
if host not in SOURCE_POLICY:
raise PermissionError("Inventory source is not approved")
return host
def solve_cloudflare_challenge(
url: str,
chrome_user_agent: str,
fresh_html: str = "",
) -> dict:
host = approved_host(url)
profile = SOURCE_POLICY[host]["proxy_profile"]
task = {
"type": "AntiCloudflareTask",
"websiteURL": url,
"proxy": PROXY_VAULT[profile],
"userAgent": chrome_user_agent,
}
if fresh_html:
task["html"] = fresh_html
solution = capsolver.solve(task)
cookies = solution.get("cookies") or {}
clearance = cookies.get("cf_clearance") or solution.get("token")
if not clearance:
raise RuntimeError("Challenge solution did not include clearance")
return {
"cookies": cookies,
"user_agent": solution.get("userAgent") or chrome_user_agent,
"proxy_profile": profile,
}
Utilice un proxy estático o pegajoso. No rote la identidad de red entre navegación inicial, resolución y recuperación de página.
Cree el contexto de Playwright con el proxy y agente de usuario aprobado, capture el estado del desafío, obtenga la solución y aplique cookies dentro de un contexto compatible.
from urllib.parse import urlparse
async def recover_inventory_page(browser, url: str):
host = approved_host(url)
profile = SOURCE_POLICY[host]["proxy_profile"]
proxy = PROXY_VAULT[profile]
bootstrap_context = await browser.new_context(
proxy={"server": proxy},
)
bootstrap_page = await bootstrap_context.new_page()
await bootstrap_page.goto(url, wait_until="domcontentloaded")
state = await classify_page(bootstrap_page)
if state != "CLOUDFLARE_CHALLENGE":
return bootstrap_context, bootstrap_page, False
user_agent = await bootstrap_page.evaluate("navigator.userAgent")
html = await bootstrap_page.content()
solution = solve_cloudflare_challenge(
url=url,
chrome_user_agent=user_agent,
fresh_html=html,
)
await bootstrap_context.close()
context = await browser.new_context(
proxy={"server": proxy},
user_agent=solution["user_agent"],
)
cookie_domain = urlparse(url).hostname
await context.add_cookies([
{
"name": name,
"value": value,
"domain": cookie_domain,
"path": "/",
"secure": True,
"httpOnly": True,
}
for name, value in solution["cookies"].items()
])
page = await context.new_page()
await page.goto(url, wait_until="domcontentloaded")
return context, page, True
Los diferentes formatos de proxy requieren diferentes campos de Playwright. Parsee el servidor de proxy, nombre de usuario y contraseña dentro del adaptador del cofre cuando sea necesario.
Prefiera JSON-LD o contratos de página estables sobre texto de presentación.
import json
SCHEMA_AVAILABILITY = {
"https://schema.org/InStock": "IN_STOCK",
"https://schema.org/OutOfStock": "OUT_OF_STOCK",
"https://schema.org/PreOrder": "PREORDER",
"https://schema.org/BackOrder": "BACKORDER",
"InStock": "IN_STOCK",
"OutOfStock": "OUT_OF_STOCK",
}
async def read_jsonld_offers(page) -> list[dict]:
blocks = await page.locator(
'script[type="application/ld+json"]'
).all_text_contents()
offers = []
for raw in blocks:
try:
data = json.loads(raw)
except json.JSONDecodeError:
continue
nodes = data if isinstance(data, list) else [data]
for node in nodes:
if not isinstance(node, dict):
continue
offer = node.get("offers")
if isinstance(offer, dict):
offers.append(offer)
elif isinstance(offer, list):
offers.extend(x for x in offer if isinstance(x, dict))
return offers
Normalice la disponibilidad sin inventar la cantidad:
def normalize_offer_availability(offer: dict) -> tuple[str, int | None]:
raw = str(offer.get("availability", ""))
availability = SCHEMA_AVAILABILITY.get(raw, "UNKNOWN")
inventory_level = offer.get("inventoryLevel")
quantity = None
if isinstance(inventory_level, dict):
value = inventory_level.get("value")
if isinstance(value, int) and value >= 0:
quantity = value
return availability, quantity
Almacene un hash de la evidencia relevante y versión del analizador. Esto hace que las alertas sean reproducibles sin retener contenido de página innecesario.
Alerte sobre transiciones, no sobre capturas repetidas.
def inventory_transition(previous: str, current: str) -> str | None:
if previous == current:
return None
if previous in {"OUT_OF_STOCK", "UNKNOWN"} and current == "IN_STOCK":
return "RESTOCKED"
if previous == "IN_STOCK" and current == "OUT_OF_STOCK":
return "SOLD_OUT"
return "STATUS_CHANGED"
Requiera dos observaciones cuando la fuente sea ruidosa:
def confirmed_transition(observations: list[InventoryObservation]) -> str | None:
if len(observations) < 3:
return None
older, previous, current = observations[-3:]
if previous.availability != current.availability:
return None
return inventory_transition(older.availability, current.availability)
La segunda muestra reduce alertas causadas por un error temporal del analizador o estado de página. Ajuste la regla según la cadencia de actualización de la fuente.
Un evento de desafío es una señal de infraestructura. No es un cambio de inventario.
| Métrica | Significado | Destino de alerta |
|---|---|---|
inventory_restock_total |
Transición confirmada de no disponible a disponible | Operaciones de comercio electrónico |
inventory_unknown_total |
El analizador no pudo determinar la disponibilidad | Cola de calidad de datos |
challenge_encounter_total |
Una página aprobada presentó un desafío | Operaciones de automatización |
challenge_recovery_success |
La recuperación se completó y la página de producto regresó | Tablero de confiabilidad |
challenge_loop_total |
La página permaneció desafiada después de la recuperación | Revisión del operador |
Nunca clasifique una página de desafío, error HTTP o selector vacío como OUT_OF_STOCK.
La Preguntas frecuentes sobre errores de CapSolver proporciona orientación diagnóstica, y la entrada de blog de automatización de CapSolver cubre patrones de recuperación relacionados.
Código de bonificación: Usa el código WEBS en el Panel de control de CapSolver para obtener un 5% adicional en cada recarga.
| Control | Implementación recomendada |
|---|---|
| Permisos de origen | Registro de aprobación por host y límite de propósito |
| Prioridad de origen | Feed o API antes de la caída al navegador |
| Proxy | Servidor resuelto estático o con perfil persistente |
| Agente de usuario | Identidad de Chrome compatible a través de la recuperación |
| Cookies | Almacenamiento encriptado de corta duración; sin retención de análisis |
| Reintento | Un intento de recuperación, luego revisión por operador |
| Límite de velocidad | Cuotas específicas por fuente con retroalimentación y jitter |
| Alertas | Notificación de solo lectura por defecto |
| Acción de alto impacto | Confirmación explícita antes de la reserva o compra |
Utiliza la Preguntas frecuentes de resolución de CAPTCHA de CapSolver para comprender el flujo de tareas y la página de productos de CapSolver para revisar las categorías de soluciones admitidas.
Monitorea solo fuentes a las que tengas autorización para acceder. Sigue las licencias de API de mercado, términos del comerciante, límites de velocidad, requisitos de privacidad y contratos de datos de inventario. No uses la recuperación de desafíos para acceder a cuentas privadas, dashboards de vendedores restringidos, registros de compradores o inventario no público. Mantén el sistema de solo lectura, a menos que un servicio aprobado separado maneje la reserva o el pago con consentimiento humano explícito.
La recuperación de desafíos de Cloudflare puede hacer que el monitoreo de inventario de comercio electrónico sea más confiable, pero solo cuando esté dentro de un canal de datos orientado a API, consciente de variantes y controlado por políticas. El monitor debe validar la identidad de la página, preservar la consistencia del proxy y el agente de usuario, consumir las cookies de autorización brevemente, analizar evidencia de disponibilidad estructurada y separar fallos de infraestructura de cambios reales en el stock.
Inicia un flujo de trabajo aprobado con CapSolver, pruébalo contra una fuente controlada y agrega retención de evidencia, límites de velocidad y revisión por operador antes de escalar.
No. Prepara feeds de comerciantes, APIs de mercados, APIs de vendedores y fuentes de datos licenciadas. Usa un navegador autorizado solo para brechas permitidas o validación orientada al comprador.
Usa la AntiCloudflareTask documentada con la URL de destino exacta y un proxy estático o persistente. Los campos opcionales incluyen el agente de usuario de Chrome compatible del navegador y el HTML de desafío reciente.
No. Un desafío, página de error o selector ausente es un estado de infraestructura o analizador. Registra DESCONOCIDO y enróvalo por separado de las transiciones de inventario.
Conserva solo en almacenamiento encriptado de corta duración. No las coloques en contexto de modelo, tablas de análisis, alertas o registros a largo plazo.
Mantén el monitoreo de solo lectura por defecto. Las reservas, compras y pago requieren un servicio aprobado separado, validación de precios reciente, límites de política y confirmación humana explícita.
Corrija un token de Turnstile inválido al verificar el vencimiento, la clave del sitio, la acción, el cdata, el estado del navegador, la verificación del servidor y los reintentos limitados de CapSolver.

Construya un flujo de trabajo de MCP de Cloudflare Turnstile con CapSolver, reintentos limitados, registros con datos eliminados, verificaciones de sesión y validación de resultados.

Construye un solucionador de Cloudflare Turnstile con transferencia de sesión de CapSolver, middleware de descarga, límites de reintentos y verificación de contenido.

Una guía de reparación basada en trazas para agentes de Cursor que interactúan con Cloudflare, enfocada en parámetros de Turnstile, validación del tráfico, cookies, señales 403/429 y reglas de detención del planificador.
