← Todos los artículos

Llama a Cualquier Plugin de ScrapeUnblocker Desde Python, Node.js, PHP o Ruby

Los plugins son la forma más rápida de obtener datos estructurados de un sitio concreto. Envías una palabra clave o un ID y recibes JSON limpio, sin selectores que mantener. La pregunta siempre ha sido cuánto código de pegamento hay entre tu proyecto y ese JSON.

Desde el SDK 0.11.0, muy poco. Los clientes de Python, Node.js, PHP y Ruby tienen un método para cada plugin público, además de una llamada genérica para cualquier endpoint de plugin. Esta guía explica cómo funcionan los métodos, recorre un pequeño script que consulta varias tiendas y cubre lo que importa cuando lo pones a correr de forma programada: la concurrencia y el manejo de errores.

Qué Ha Cambiado

Llegaron tres cosas a la vez:

  • Un método para cada plugin en los cuatro SDK. La vista general de plugins ya lista más de 60 plugins en 14 categorías: e-commerce, supermercados, viajes, Google, otros buscadores, inmobiliario, vehículos, empleo, reseñas, negocios locales, apps, vídeo y música, y SEO y publicidad. Cada uno tiene su método.
  • Una página de documentación por plugin. Cada página lista los campos, muestra una respuesta de ejemplo e incluye la llamada en cURL, Python, Node.js, PHP y Ruby, una al lado de la otra.
  • Plugins en el servidor MCP. El servidor MCP y el conector alojado incorporan dos herramientas, list_plugins y run_plugin, para que un asistente de IA pueda encontrar y ejecutar los mismos plugins.

Instala el SDK

Elige tu lenguaje:

pip install scrapeunblocker              # Python 3.8+
npm install scrapeunblocker              # Node.js 18+
composer require scrapeunblocker/client  # PHP 8.1+
gem install scrapeunblocker              # Ruby 2.7+

Después guarda tu API key en una variable de entorno. Los cuatro clientes la leen automáticamente:

export SCRAPEUNBLOCKER_KEY="YOUR_API_KEY"

La key la obtienes en el dashboard. Si ya tienes un SDK instalado, actualiza a la 0.11.0 o posterior para tener todos los métodos de plugins.

Cómo Funcionan los Métodos de Plugin

El patrón es el mismo en todos los lenguajes, así que en cuanto usas un plugin sabes usarlos todos:

  • El método se llama como el plugin. Walmart Search es walmart_search en Python y Ruby, y walmartSearch en Node.js y PHP.
  • La entrada principal va primero. Una palabra clave, un ID de producto o un dominio es el primer argumento.
  • Todo lo demás es una opción. Argumentos con nombre en Python y Ruby, un objeto de opciones en Node.js (claves en camelCase) y un array con los nombres de parámetro de la API en PHP.
  • Las opciones que no pasas no se envían. Se aplican los valores por defecto de la propia API, así que solo indicas lo que quieres cambiar.
  • Las listas se gestionan solas. Si un plugin acepta varios valores, pasa una lista y el SDK la envía separada por comas.

Esta es la misma búsqueda en Best Buy en los cuatro lenguajes:

# Python
result = su.bestbuy_search("laptop", sort="price_low", max_results=48)
// Node.js
const result = await su.bestbuySearch("laptop", { sort: "price_low", maxResults: 48 });
// PHP
$result = $su->bestbuySearch('laptop', ['sort' => 'price_low', 'max_results' => 48]);
# Ruby
result = su.bestbuy_search("laptop", sort: "price_low", max_results: 48)

En todos los casos su es el cliente: Client() en Python, new ScrapeUnblockerClient() en Node.js, new Client() en PHP y ScrapeUnblocker::Client.new en Ruby.

Ejemplo: Compara Precios en Tres Tiendas

Un buen primer proyecto es comparar precios entre tiendas. Walmart, Target y Best Buy tienen cada una un plugin de búsqueda, y los tres aceptan las mismas opciones sort="price_low" y max_results. Sus respuestas, en cambio, no son idénticas. Cada plugin devuelve los campos que usa el propio sitio:

  • Walmart llama al nombre del producto name, a su ID id y al precio anterior wasPrice.
  • Target usa title y su propio ID de producto, tcin.
  • Best Buy usa title, sku y originalPrice, y añade un número de model.

Un campo sin valor se omite por completo en ese producto. Así que lo primero es llevar las tres formas a una sola:

from scrapeunblocker import Client

su = Client()  # reads SCRAPEUNBLOCKER_KEY
QUERY = "wireless headphones"

def normalize(store, item):
    return {
        "store": store,
        "id": item.get("id") or item.get("tcin") or item.get("sku"),
        "title": item.get("name") or item.get("title"),
        "brand": item.get("brand") or "",
        "price": item.get("price"),
        "regular_price": item.get("wasPrice") or item.get("originalPrice"),
        "url": item.get("url"),
    }

stores = {
    "walmart": su.walmart_search,
    "target": su.target_search,
    "bestbuy": su.bestbuy_search,
}

rows = []
for store, search in stores.items():
    result = search(QUERY, sort="price_low", max_results=48)
    rows += [normalize(store, p) for p in result.get("products", [])]

sony = [r for r in rows if r["brand"].lower() == "sony" and r["price"]]
for r in sorted(sony, key=lambda r: r["price"])[:10]:
    print(f'{r["store"]:8} {r["price"]:>8.2f}  {r["title"][:60]}')

Tres llamadas, una tabla, y cada fila con tienda, precio y enlace. A partir de aquí puedes guardar las filas en una base de datos una vez al día y ya tienes un historial de precios.

Una advertencia honesta: lo difícil no es el scraping, sino emparejar el mismo producto entre tiendas. Los títulos cambian de una tienda a otra. Marca más número de modelo es una clave mucho mejor que el título, y Best Buy te da model directamente. Cuenta con hacer algo de emparejamiento manual en tus productos más importantes.

Ejecuta Llamadas en Paralelo Sin Recibir un 429

En cuanto sigues más de unas pocas palabras clave, las llamadas secuenciales se vuelven lentas. En Python cada método tiene su gemelo asíncrono en AsyncClient, y en Node.js cada método devuelve una promesa. Limita las llamadas simultáneas con un semáforo:

import asyncio
from scrapeunblocker import AsyncClient

QUERIES = ["wireless headphones", "air fryer", "robot vacuum", "4k tv"]
STORES = ["walmart", "target", "bestbuy"]
CONCURRENCY = 10  # keep this below your plan's concurrency limit

async def search(su, sem, store, query):
    async with sem:
        method = getattr(su, f"{store}_search")
        return store, query, await method(query, max_results=48)

async def main():
    sem = asyncio.Semaphore(CONCURRENCY)
    async with AsyncClient() as su:
        jobs = [search(su, sem, s, q) for s in STORES for q in QUERIES]
        return await asyncio.gather(*jobs, return_exceptions=True)

results = asyncio.run(main())

Por qué importa el límite: los planes se limitan por peticiones concurrentes, no por peticiones por segundo. Los límites son 20 en pago por uso, 25 en Starter, 100 en Pro, 200 en Business, 300 en Scale y 400 en Ultimate. Una petición que supera el límite recibe un 429 al instante y no se cobra. El SDK reintenta un 429 con backoff por su cuenta, pero mantenerte por debajo del límite hace que la ejecución sea rápida y predecible. Tienes los detalles en límites de concurrencia.

Gestiona los Errores Como un Pipeline, No Como un Script

Un script que ejecutas una vez puede fallar ante un error. Un trabajo que corre cada noche no debería. Los SDK lanzan errores tipados, todos subclases de ScrapeUnblockerError, y ya reintentan los transitorios (429, 502, 503, 504 y errores de red) con backoff exponencial. Una llamada a un plugin que se queda sin tiempo ahora devuelve 502 y no se cobra, así que el reintento integrado también la cubre.

Lo que te queda por gestionar a ti:

from scrapeunblocker import (
    Client,
    BudgetExceededError,
    ScrapeUnblockerError,
    ValidationError,
)

su = Client()

try:
    deals = su.bestbuy_search("oled tv", sort="discount", max_results=96)
except BudgetExceededError:
    # 402: this month's spend reached the limit you set. Stop, do not retry.
    raise SystemExit("Monthly budget reached, stopping the run")
except ValidationError as e:
    # 422: a parameter is missing or has the wrong type
    print("fix the request:", e.body)
except ScrapeUnblockerError as e:
    # anything that survived the built-in retries
    print("skipping this query:", e)

El caso de BudgetExceededError es nuevo. Ahora puedes fijar un límite de presupuesto mensual en tu perfil. Cuando el gasto del periodo de facturación lo alcanza, las llamadas devuelven 402 hasta el siguiente periodo o hasta que subas el límite. Para trabajos programados es una red de seguridad sencilla: un bucle descontrolado no te dará un susto en la factura. Los SDK nunca reintentan un 402, porque solo se resuelve cuando cambia el estado de facturación.

La lista completa de códigos de estado está en la referencia de errores.

La Salida de Emergencia plugin()

Se añaden plugins nuevos con el tiempo, y puede que la versión del SDK que tienes instalada aún no tenga método para el más reciente. Para ese caso, cada cliente tiene una llamada genérica que recibe la ruta del endpoint y sus parámetros:

data = su.plugin("/marketplace/target-search", query="tv", max_results=24)
const data = await su.plugin("/marketplace/target-search", { query: "tv", max_results: 24 });

Dos detalles a recordar. La ruta es la que aparece al principio de la página de documentación de cada plugin. Y los parámetros van con los nombres que usa la API, así que en Node.js aquí escribes max_results, no el maxResults en camelCase que aceptan los métodos con nombre.

Los Mismos Plugins Dentro de tu Asistente de IA

Si usas Claude, ChatGPT u otro cliente MCP, no necesitas código. Con las nuevas herramientas list_plugins y run_plugin, el asistente puede encontrar el plugin adecuado y ejecutarlo a partir de una petición normal como “Find coffee makers on Target under $50 and compare them with Walmart’s.” Listar plugins es gratis. Cada ejecución se cobra como una petición a la API.

La configuración está explicada en Give Claude Web Access With the ScrapeUnblocker MCP Server y en la documentación de MCP.

Preguntas Frecuentes

¿Necesito un SDK para usar los plugins? No. Cada plugin es un endpoint HTTP normal: un POST con los parámetros en la query string y tu key en la cabecera x-scrapeunblocker-key. Los SDK añaden errores tipados, reintentos y nombres de método, pero sirve cualquier cliente HTTP.

¿Cómo se cobran las llamadas a plugins? Una ejecución de plugin consume la misma cuota del plan que cualquier otra petición a la API. No hay una facturación aparte para plugins. Las llamadas rechazadas con 429, los timeouts de plugin devueltos como 502 y los bloqueos devueltos como 403 no se cobran.

¿Por qué falta un campo en algunos productos? Los plugins omiten los campos que no tienen valor en la página de origen. Un producto sin rebaja no tiene wasPrice, y una ficha de búsqueda sin marca no tiene brand. Lee los campos con un valor por defecto, como .get() en Python, en lugar de dar por hecho que existen.

¿Puedo probar un plugin antes de escribir código? Sí. Abre los plugins en el dashboard, rellena los campos y ejecútalo. Obtienes el JSON y un snippet listo para copiar a tu proyecto.

Por Dónde Empezar

Elige un sitio del que ya recojas datos a mano, busca su plugin en la vista general de plugins o en el catálogo de scrapers y sustituye tu scraper por una sola llamada a un método. Después añade el límite de concurrencia y el manejo de errores de arriba antes de programarlo.

ScrapeUnblocker se ocupa de los bloqueos, el renderizado y el parseo detrás de cada plugin, así que tu código sigue teniendo pocas líneas sea cual sea el sitio al otro lado. Si aún no tienes una key, puedes empezar en la página de precios.

Prueba ScrapeUnblocker gratis

Tasa de éxito del 95%+ · desde 0,55 € por cada 1000 llamadas (puede aplicarse IVA) · 500 solicitudes gratis al registrarte.

Pruébalo gratis → Ver precios