Primero fuimos a los sitemaps públicos de Shopee.sg y sacamos la lista de productos:
cada uno venía como un par shop_id + item_id. Esos identificadores
los guardamos en una base SQLite (~9 068 IDs en la PoC; es una muestra, no el catálogo
completo del sitio) para poder ir procesándolos de a lotes, sin depender de una API oficial.
Después abrimos las páginas de producto con Playwright detrás de un proxy residencial
de Singapur (Proxies.Vision, sesión sticky). Del HTML guest leímos el bloque
PDP_BFF_DATA: ahí salían título, marca, imágenes, categoría, stock,
descripción y las variantes color×size. Así armamos el catálogo — 62 productos y
251 filas de variantes — con un hit rate de alrededor del 69%. Cuando Shopee pedía
verificar el tráfico, rotábamos la sesión del proxy y seguíamos.
Para los precios entramos a las páginas de cada shop, capturamos el XHR de las cards
de producto (item_card_display_price, valores en micros → SGD) y los
unimos al catálogo por item_id. Con ScrapingBee stealth reforzamos algunas
lecturas de shop. Así obtuvimos precios reales en al menos cinco ítems y cerramos el
loop de la PoC, sin cuentas de Gmail, Facebook ni teléfono.
No fueron necesarias. Todo el recorrido de esta PoC — discover por sitemap, enrich del catálogo en guest y precios desde las páginas de shop — se hizo sin login de Shopee y sin crear cuentas de Gmail, Facebook ni números de teléfono.
Sí hubo limitantes, propias del método guest. En la página individual del producto
el HTML no trae precio/sold de forma fiable, así que esos campos los resolvemos desde
las páginas de shop (cards / XHR) y un join por item_id: funciona, pero
implica visitar shops además del PDP.
En esta PoC no buscamos cobertura total de precio/sold en los 62 ítems: el umbral era
demostrar el loop. Quedó our_price en 5/62, y list_price /
units_sold en 4/62 con el mismo path. A producción se completa recorriendo
más shops. Los ~9 068 IDs del discover son una muestra de los sitemaps (el catálogo
real del sitio es mucho mayor). De vez en cuando aparece un challenge de tráfico
(verify): se mitiga rotando la sesión sticky del proxy.
La inversión total en la PoC fue de aproximadamente USD 15: créditos y herramientas que fuimos cargando mientras armábamos el recorrido (proxy, trials de scraping, captcha, etc.).
El costo real de lo que terminó sirviendo para el resultado (catálogo + precios) fue mucho menor: ≈ USD 0.50 – 2 en tráfico de proxy residencial Proxies.Vision, más ScrapingBee en trial a USD 0. El resto de la inversión quedó como saldo/crédito de prueba, no como gasto necesario del método que cerró el informe.
Con el mismo método de la PoC (sitemaps → enrich de PDP con proxy → precios desde
páginas de shop y join por item_id), llevar el catálogo de Singapur a
alrededor de un millón de ítems con precio se estima en
USD 2 200 – 6 000.
El rango depende sobre todo del tráfico de proxy residencial y de cuán profundo
haya que recorrer las shops para cubrir precios en casi todo el set.
| Proveedor | Para qué | Gasto útil |
|---|---|---|
| Proxies.Vision | Proxy residencial SG sticky: enrich de PDP (catálogo) y XHR de precios en páginas de shop | ≈ USD 0.50 – 2 |
| ScrapingBee | Stealth sobre páginas de shop para reforzar la lectura de precios | USD 0 (trial) |
Inversión total de la PoC ≈ USD 15 (incluye créditos auxiliares de prueba). Gasto útil del método del informe ≈ USD 0.50 – 2.
El objetivo pide 18 campos por producto/variante. Sobre los 62 productos y 251 variantes de esta PoC, esto es lo que obtuvimos (actualizado tras completar el harvest de shop pages):
| Estado | Campos |
|---|---|
| OK (~100%) | brand_name, title, url,
ec_bread_crumb1, image_url, images_url,
offering_availability, website_sku, ec_website_sku,
has_retail_offer, has_3p_offer,
product_description (~93–97%),
merchants — 62/62 (nombre de shop vía páginas de shop / PDP guest) |
| Parcial |
our_price — 5/62 (método shop cards; cobertura PoC, no full set).list_price — 4/62 (strikethrough / before-discount en las mismas cards).units_sold — 4/62 (historical_sold en el mismo path de shop).color / size_name — solo cuando el ítem declara esa dimensión (~47% / ~10% a nivel producto).
|
| Falta a escala | No hay un campo del brief en 0/62 tras este pase: los huecos de precio/sold/list son de cobertura (hay que recorrer más shops con el mismo método), no de un dato imposible en guest. El antibot (verify) frena el ritmo; no cambia el procedimiento. |
Conclusión: el método guest (PDP + páginas de shop) cubre el brief.
Cerramos merchants al 100% del set PoC. our_price,
list_price y units_sold salen del mismo tipo de respuesta de shop;
en esta corrida quedaron demostrados en 4–5 ítems — escalar = más crawl de shops, mismo join por item_id.
Cargando dataset…