Files
fn_registry/python/functions/datascience/scrape_gumroad_discover.md
T
2026-07-03 00:48:43 +02:00

5.8 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_gumroad_discover function py datascience 1.0.0 impure def scrape_gumroad_discover(taxonomy: str, sort: str = 'best_selling', max_products: int = 300, page_size: int = 100) -> list[dict] Scrapea el marketplace publico de Gumroad Discover usando el endpoint JSON verificado gumroad.com/products/search (taxonomy+sort+from+size). Recolecta los productos de una taxonomy (nicho) ordenados por el criterio elegido y estampa en cada producto el total de la taxonomy (saturacion del nicho). Normaliza cada producto a un dict plano con id, seller_name, ratings, precio (cents/usd), pay-what-you-want/free, native_type, url y metadatos de scrape (taxonomy, total_in_taxonomy, sort_used, rank 0-based). Solo stdlib (urllib+json+time).
gumroad
scraping
market-intel
trends
datascience
false error_go_core
true
test_normaliza_producto_a_dict_plano
test_paginacion_para_al_agotar_ventana
test_sort_invalido_lanza_valueerror
test_body_no_json_lanza_runtimeerror
python/functions/datascience/scrape_gumroad_discover_test.py python/functions/datascience/scrape_gumroad_discover.py
name desc
taxonomy Slug de taxonomy / nicho de Gumroad (ej. 'design', 'business-and-money', '3d'). Determina el segmento de mercado scrapeado y el valor total_in_taxonomy (numero total de productos = saturacion del nicho) que se estampa en cada producto.
name desc
sort Criterio de orden. Uno de: best_selling, most_reviewed, hot_and_new, highest_rated, newest, price_asc, price_desc. Cualquier otro valor lanza ValueError. Default 'best_selling'.
name desc
max_products Cota superior de productos a recolectar entre paginas. Default 300. La ventana de paginacion de Gumroad es finita (from~960 aun devuelve datos), asi que valores muy altos pueden recibir menos productos de los pedidos.
name desc
page_size Numero de productos pedidos por pagina via 'size'. Gumroad admite al menos 300. Una pagina que devuelve menos de page_size items señala el fin de la ventana y detiene la paginacion. Default 100.
Lista de dicts planos, uno por producto, con exactamente estas claves: id, permalink, name, seller_name, ratings_count, ratings_avg, price_cents, currency_code, price_usd (float = price_cents/100), is_pay_what_you_want (bool), is_free (bool = price_cents==0), native_type, url, taxonomy (el arg), total_in_taxonomy (el 'total' del JSON = saturacion del nicho), sort_used (el arg sort), rank (posicion 0-based en el orden devuelto).

Ejemplo

import sys, os
sys.path.insert(0, os.path.join("python", "functions"))
from datascience.scrape_gumroad_discover import scrape_gumroad_discover

# Top best-sellers del nicho "design" en Gumroad Discover
rows = scrape_gumroad_discover(taxonomy="design", sort="best_selling", max_products=300, page_size=100)
print(len(rows), "productos")
print("saturacion del nicho:", rows[0]["total_in_taxonomy"])
print(rows[0])
# {'id': '...', 'permalink': '...', 'name': '...', 'seller_name': '...',
#  'ratings_count': 128, 'ratings_avg': 4.9, 'price_cents': 2900,
#  'currency_code': 'usd', 'price_usd': 29.0, 'is_pay_what_you_want': False,
#  'is_free': False, 'native_type': 'digital', 'url': 'https://...',
#  'taxonomy': 'design', 'total_in_taxonomy': 4213, 'sort_used': 'best_selling', 'rank': 0}

# Productos mas nuevos de un nicho concreto
nuevos = scrape_gumroad_discover(taxonomy="3d", sort="newest", max_products=50)

Cuando usarla

Usala cuando quieras hacer market intelligence sobre productos digitales: descubrir que se vende mas en un nicho de Gumroad, medir la saturacion del nicho (total_in_taxonomy) y capturar precios, valoraciones y vendedores para decidir si un nicho merece la pena o esta saturado. Es la fuente de un pipeline de deteccion de oportunidades de producto digital (grupo market-intel): scrapea varias taxonomies/sorts, cruza los snapshots y prioriza nichos con demanda alta y competencia manejable. Llamala antes de cualquier analisis de catalogo digital; el dict devuelto es plano y esta listo para insertar en una tabla tras añadir snapshot_date/scraped_at.

Gotchas

  • ratings.count son REVIEWS, no ventas: ratings_count cuenta valoraciones dejadas, NO unidades vendidas. Como proxy de ventas hay que multiplicar por un factor incierto (solo una fraccion de compradores valora, y esa fraccion varia por nicho/precio). Trata ratings_count como un limite inferior ruidoso de la demanda, no como ventas reales.
  • price=0 no siempre significa gratis util: price_cents==0 marca is_free=True, pero puede tratarse de un producto pay-what-you-want (is_pay_what_you_want=True) con minimo 0, no de un regalo. Cruza siempre is_free con is_pay_what_you_want antes de sacar conclusiones de precio.
  • Ventana de paginacion finita: page/per_page se IGNORAN (siempre devuelven desde 0); solo from+size paginan. La ventana es amplia pero finita (from~960 aun devuelve, mas alla se agota). Pedir max_products muy alto puede recibir menos productos de los pedidos: la funcion para cuando una pagina devuelve menos de page_size items.
  • Cloudflare bloquea sin UA de navegador: el endpoint exige Accept: application/json y un User-Agent de navegador. Sin ello Gumroad/Cloudflare puede devolver una pagina de challenge en HTML (no JSON) o redirigir. La funcion ya envia un UA de Chrome; si aun asi recibe un body no-JSON lanza RuntimeError claro — en ese caso cae al navegador del ecosistema (browser MCP / CDP).
  • Moneda no siempre USD: price_usd es solo price_cents/100 por conveniencia; si currency_code != 'usd' el valor NO esta convertido a dolares. Conserva y usa currency_code para convertir tu mismo.