Files
fn_registry/python/functions/browser/scrape_amazon_movers_cdp.md
T
egutierrez 763e06c127 feat(browser): auto-commit con 178 cambios
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-20 18:22:23 +02:00

6.0 KiB

name, kind, lang, domain, version, purity, signature, description, tags, uses_functions, uses_types, returns, returns_optional, error_type, imports, tested, tests, test_file_path, file_path, params, output
name kind lang domain version purity signature description tags uses_functions uses_types returns returns_optional error_type imports tested tests test_file_path file_path params output
scrape_amazon_movers_cdp function py browser 1.0.0 impure def scrape_amazon_movers_cdp(marketplace: str = 'amazon.es', categories: list[str] | None = None, port: int = 9222, max_items: int = 30, timeout_s: float = 25.0) -> dict Scraper de Amazon Movers & Shakers (productos que mas suben en ranking de ventas = demanda emergente, clave dropshipping) via Chrome DevTools Protocol. La pagina monta las cards por JavaScript (el GET HTTP devuelve 0 productos), asi que renderiza via CDP, espera el grid async, extrae el outerHTML y lo pasa al parser puro parse_amazon_ranking_html. Aporta precio de venta + % de subida de ranking por producto. Nunca lanza ni inventa datos.
amazon
movers
cdp
dropship
market-intel
browser
scraping
cdp_open_url_and_wait_py_pipelines
cdp_eval_py_browser
parse_amazon_ranking_html_py_datascience
false error_go_core
websocket
false
python/functions/browser/scrape_amazon_movers_cdp.py
name desc
marketplace Dominio Amazon objetivo (amazon.es, amazon.com, ...). Determina la URL de movers y la moneda fallback del parser. Para España usa amazon.es (precios en EUR).
name desc
categories Lista de slugs de categoria de movers (ej. 'automotive' para coche, 'pet-supplies' para mascotas). Si es None scrapea la portada general de movers. Cada slug navega a /gp/movers-and-shakers/<slug>.
name desc
port Puerto de remote debugging del Chrome a usar. Default 9222 (chromium-personal residential de produccion, pasa el anti-bot mejor que requests). Para un Chrome aislado apunta a 9333 (browser_mcp).
name desc
max_items Numero maximo de productos recolectados por categoria. Default 30.
name desc
timeout_s Timeout (segundos) por categoria, tanto para la navegacion como para el polling de aparicion de cards. Default 25.0.
dict autosuficiente {status, source:'amazon_movers', count, products:[...]}. status='ok' si extrajo productos; 'error' si no hubo cards (categoria sin movers ahora, o chromium degradado); 'captcha' si Amazon sirvio un interstitial anti-bot. Cada product: marketplace, list_type ('movers_shakers'), category, rank (int), asin, title, price (float EUR), currency, rating (float|None), reviews (int|None), pct_change (float|None), url, source ('amazon_movers'), scraped_at (ISO8601 UTC). En error/captcha products=[] y se incluye 'error' con el mensaje.

Ejemplo

import sys, os, json
sys.path.insert(0, os.path.join("python", "functions"))
from browser.scrape_amazon_movers_cdp import scrape_amazon_movers_cdp

# Movers & Shakers de coche y mascotas en amazon.es (chromium-personal en 9222).
out = scrape_amazon_movers_cdp(
    marketplace="amazon.es",
    categories=["automotive", "pet-supplies"],
    port=9222,
    max_items=30,
    timeout_s=25.0,
)
print(out["status"], out.get("count"))
if out["status"] == "ok":
    print(json.dumps(out["products"][0], ensure_ascii=False, indent=2))
    # {'marketplace': 'amazon.es', 'list_type': 'movers_shakers', 'category': 'automotive',
    #  'rank': 1, 'asin': 'B0...', 'title': '...', 'price': 19.99, 'currency': 'EUR',
    #  'rating': 4.1, 'reviews': 380, 'pct_change': 150.0, 'url': 'https://www.amazon.es/dp/B0...',
    #  'source': 'amazon_movers', 'scraped_at': '2026-06-20T...'}

Tambien lanzable por CLI:

cd $HOME/fn_registry
python/.venv/bin/python3 python/functions/browser/scrape_amazon_movers_cdp.py \
  --marketplace amazon.es --categories automotive,pet-supplies --port 9222

Cuando usarla

Usala cuando quieras captar demanda EMERGENTE en Amazon (no lo que mas se vende ya, sino lo que mas SUBE de golpe en ranking de ventas en 24h) para market intelligence de dropshipping. Es la fuente de senal de "nichos en alza": cada producto trae precio de venta en el marketplace y el % de subida de ranking. Alternativa renderizada al scraper HTTP scrape_amazon_bestsellers cuando ese cae por anti-bot o cuando necesitas movers (que se montan por JS y no salen en el GET puro). Combinala con un upsert a DuckDB/Postgres + snapshots diarios para detectar tendencias.

Gotchas

  • Necesita un Chrome con remote debugging vivo en port. Por defecto 9222 (el navegador diario residential). Si no hay Chrome usable devuelve status='error' con un mensaje claro (no lanza). El chromium-personal debe estar logueado y con sesion limpia; un chromium recien arrancado sin sesion puede recibir una pagina degradada de Amazon.
  • Amazon puede no tener movers para una categoria AHORA. La pagina muestra literalmente "no movers and shakers available in this category. Please check back later." En ese caso devuelve status='error' con ese motivo y products=[] — NO inventa datos. La disponibilidad de movers varia por categoria, marketplace y hora; reintenta mas tarde o prueba otra categoria/marketplace.
  • Captcha / anti-bot. Si Amazon sirve un interstitial de verificacion, devuelve status='captcha'. Reaccion correcta: handoff humano (activar la pestana y resolver a mano), no auto-resolver — el token va atado a esa sesion.
  • DOM fragil. Amazon rota plantillas del grid (A/B test). El parser puro tiene fallbacks por campo; aun asi, si Amazon rompe la plantilla, el scraper devuelve status='error' ("se montaron N cards pero el parser no extrajo productos"). Mantener selectores en parse_amazon_ranking_html.
  • Render async: el load event NO garantiza cards en el DOM; la funcion hace polling (querySelectorAll(...).length) cada ~1s hasta que el grid monta o se agota timeout_s.
  • Una pestana por categoria: cada slug crea un tab nuevo en el Chrome remoto. Listas largas de categorias abren muchos tabs — espacia o limpia pestanas si scrapeas muchas.
  • Campos opcionales = None: no todos los productos traen rating/reviews/pct_change. pct_change solo se rellena cuando el card de movers expone el badge de subida de ranking.