feat(shell): auto-commit con 31 cambios
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
---
|
||||
name: scrape_aliexpress_trending
|
||||
kind: function
|
||||
lang: py
|
||||
domain: datascience
|
||||
version: "1.0.0"
|
||||
purity: impure
|
||||
signature: "def scrape_aliexpress_trending(query: str | None = None, category: str | None = None, limit: int = 40, ship_to: str = 'ES') -> list[dict]"
|
||||
description: "Capta productos populares de AliExpress como señal de e-commerce/dropshipping (orders, rating, precio). Hace una request HTTP a la página de listado ordenada por número de pedidos y extrae el JSON embebido en el HTML (window.runParams / _dida_config). Best-effort: ante anti-bot lanza RuntimeError, ante HTML sin JSON devuelve []. NUNCA inventa datos."
|
||||
tags: [aliexpress, ecommerce, dropshipping, trends, market-intel, datascience]
|
||||
params:
|
||||
- name: query
|
||||
desc: "Texto de búsqueda (ej. 'kitchen gadgets'). Si se da, manda en la URL sobre category."
|
||||
- name: category
|
||||
desc: "ID numérico de categoría AliExpress o slug. Ignorado si hay query. None usa un listado 'hot products' genérico."
|
||||
- name: limit
|
||||
desc: "Número máximo de productos a devolver. Default 40."
|
||||
- name: ship_to
|
||||
desc: "Código de país ISO-2 (ES, US, GB, DE, ...) que fija región y moneda via cookies de AliExpress. Default 'ES'."
|
||||
output: "Lista de dicts con claves exactas (casan 1:1 con la tabla Postgres aliexpress_trends, sin id/snapshot_date/scraped_at): category (str|None), product_id (str), title (str|None), price (float|None), currency (str|None), orders (int|None), rating (float|None), url (str). Lista vacía si el HTML no traía JSON parseable."
|
||||
uses_functions: []
|
||||
uses_types: []
|
||||
returns: []
|
||||
returns_optional: false
|
||||
error_type: "error_go_core"
|
||||
imports: [requests]
|
||||
tested: false
|
||||
tests: []
|
||||
test_file_path: ""
|
||||
file_path: "python/functions/datascience/scrape_aliexpress_trending.py"
|
||||
---
|
||||
|
||||
## Ejemplo
|
||||
|
||||
```python
|
||||
import sys, os
|
||||
sys.path.insert(0, os.path.join("python", "functions"))
|
||||
from datascience.scrape_aliexpress_trending import scrape_aliexpress_trending
|
||||
|
||||
# Top productos por número de pedidos para una búsqueda concreta, enviando a España.
|
||||
rows = scrape_aliexpress_trending(query="phone holder", limit=20, ship_to="ES")
|
||||
for r in rows[:3]:
|
||||
print(r["title"], "->", r["orders"], "pedidos |", r["price"], r["currency"])
|
||||
|
||||
# Cada dict (las 8 claves casan con la tabla aliexpress_trends):
|
||||
# {"category": "phone holder", "product_id": "100500...", "title": "...",
|
||||
# "price": 3.21, "currency": "EUR", "orders": 12000, "rating": 4.8,
|
||||
# "url": "https://www.aliexpress.com/item/100500....html"}
|
||||
```
|
||||
|
||||
## Cuando usarla
|
||||
|
||||
Cuando necesites una señal de qué productos están vendiendo bien en AliExpress para
|
||||
research de dropshipping o market-intel: detectar tendencias, sourcing de productos
|
||||
ganadores, o alimentar un histórico (tabla `aliexpress_trends`) que cruce orders /
|
||||
rating / precio por categoría. Úsala antes de decidir un nicho o para vigilar
|
||||
periódicamente una keyword. El output va directo a un `INSERT` Postgres (las 8 claves
|
||||
coinciden con las columnas no autogeneradas).
|
||||
|
||||
## Gotchas
|
||||
|
||||
- **Anti-bot fuerte (CRÍTICO):** AliExpress bloquea agresivamente headless/datacenter
|
||||
con captcha (`/_____tmd_____/punish`), 403/429 y fingerprinting. Desde una IP de
|
||||
datacenter o un patrón de scraping evidente, esta función **lanzará `RuntimeError`**
|
||||
con frecuencia. Para extracción fiable y sostenida, la alternativa robusta es el
|
||||
**browser MCP/CDP con sesión real** (Chrome del usuario, cookies legítimas), no
|
||||
`requests`. Esta función es la vía barata; si falla repetidamente, sube de nivel.
|
||||
- **JSON embebido volátil:** el nombre/estructura del blob (`window.runParams`,
|
||||
`_dida_config_`, `_init_data_`) cambia con frecuencia. Se prueban varios patrones y
|
||||
un walk genérico, pero si AliExpress cambia el layout la función devuelve `[]`
|
||||
(HTML válido sin JSON parseable) — **NO inventa datos**. Diferencia clave:
|
||||
`RuntimeError` = bloqueado; `[]` = layout cambiado o shell vacío.
|
||||
- **Región/moneda dependen de `ship_to`:** se setean por cookies (`aep_usuc_f`,
|
||||
`intl_locale`). Un `ship_to` no mapeado cae a `ES`/`EUR`. El `currency` devuelto
|
||||
depende de lo que AliExpress decida servir, no se fuerza tras el fetch.
|
||||
- **`orders`/`price`/`rating` pueden venir `None`** si el item no expone ese campo en
|
||||
el JSON (productos nuevos sin ventas, listados sin rating). No asumir no-null.
|
||||
- **Una sola página:** devuelve hasta `limit` items de la primera página de resultados;
|
||||
no pagina. Para más volumen, llamar con queries/categorías distintas.
|
||||
- **Sin reintentos ni rotación de proxy/UA:** es una request única con headers fijos.
|
||||
Para uso periódico, orquestar reintentos y backoff fuera de la función.
|
||||
Reference in New Issue
Block a user