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,77 @@
|
||||
---
|
||||
name: scrape_google_trends
|
||||
kind: function
|
||||
lang: py
|
||||
domain: datascience
|
||||
version: "1.0.0"
|
||||
purity: impure
|
||||
signature: "def scrape_google_trends(keywords: list[str], geo: str = \"ES\", timeframe: str = \"now 7-d\", include_related: bool = True) -> list[dict]"
|
||||
description: "Capta interes de busqueda de Google Trends por keyword/nicho via pytrends. El interes es relativo 0-100, NUNCA volumen absoluto. Aplana interest_over_time + related_queries (rising/top) en filas con schema fijo que casa 1:1 con la tabla Postgres google_trends. Backoff/retry ante 429."
|
||||
tags: [google-trends, pytrends, trends, market-intel, datascience]
|
||||
uses_functions: []
|
||||
uses_types: []
|
||||
returns: []
|
||||
returns_optional: false
|
||||
error_type: "error_go_core"
|
||||
imports: [pytrends, time]
|
||||
params:
|
||||
- name: keywords
|
||||
desc: "lista de terminos/nichos a consultar (max 5 por payload, limite de Google Trends). Cada elemento es una keyword string."
|
||||
- name: geo
|
||||
desc: "codigo de pais ISO-3166 (ej. 'ES', 'US', '' para mundial). Default 'ES'."
|
||||
- name: timeframe
|
||||
desc: "ventana temporal en sintaxis pytrends (ej. 'now 7-d', 'today 3-m', 'today 12-m', '2024-01-01 2024-12-31'). Default 'now 7-d'."
|
||||
- name: include_related
|
||||
desc: "si True anade filas metric='rising' y metric='top' de related_queries por keyword. Si False solo interest_over_time. Default True."
|
||||
output: "lista de dicts con claves EXACTAS {geo, timeframe, keyword, metric, point_date, value, related_query}. Tres tipos de fila segun metric: 'interest_over_time' (point_date=fecha ISO, value=0-100, related_query=None), 'rising' (related_query=query, value=valor rising o BREAKOUT_SENTINEL, point_date=None), 'top' (related_query=query, value=0-100, point_date=None). No incluye id/snapshot_date/scraped_at (los anade el ingest)."
|
||||
tested: false
|
||||
tests: []
|
||||
test_file_path: ""
|
||||
file_path: "python/functions/datascience/scrape_google_trends.py"
|
||||
---
|
||||
|
||||
## Ejemplo
|
||||
|
||||
```python
|
||||
import sys, os
|
||||
sys.path.insert(0, os.path.join("python", "functions"))
|
||||
from datascience.scrape_google_trends import scrape_google_trends
|
||||
|
||||
# Interes de busqueda en Espana, ultimos 7 dias, con related queries
|
||||
rows = scrape_google_trends(
|
||||
["coche electrico", "panel solar"],
|
||||
geo="ES",
|
||||
timeframe="now 7-d",
|
||||
include_related=True,
|
||||
)
|
||||
|
||||
# Cada fila tiene el mismo schema, listo para insertar en Postgres google_trends:
|
||||
# {"geo": "ES", "timeframe": "now 7-d", "keyword": "coche electrico",
|
||||
# "metric": "interest_over_time", "point_date": "2026-06-12", "value": 73,
|
||||
# "related_query": None}
|
||||
#
|
||||
# {"geo": "ES", "timeframe": "now 7-d", "keyword": "coche electrico",
|
||||
# "metric": "rising", "point_date": None, "value": 999999, # "Breakout"
|
||||
# "related_query": "ayudas coche electrico 2026"}
|
||||
#
|
||||
# {"geo": "ES", "timeframe": "now 7-d", "keyword": "panel solar",
|
||||
# "metric": "top", "point_date": None, "value": 100,
|
||||
# "related_query": "placas solares precio"}
|
||||
|
||||
interes = [r for r in rows if r["metric"] == "interest_over_time"]
|
||||
print(len(interes), "puntos de interes temporal")
|
||||
```
|
||||
|
||||
## Cuando usarla
|
||||
|
||||
Cuando necesites medir el interes/momentum de un nicho o keyword en el tiempo (market intelligence, deteccion de tendencias, validacion de demanda de producto) y vayas a persistirlo en la tabla Postgres `google_trends`. Usala antes del ingest: devuelve filas crudas con el schema exacto de la tabla, sin los campos que pone el ingest (id, snapshot_date, scraped_at). Pon `include_related=False` si solo te interesa la serie temporal y quieres minimizar la superficie de rate-limit.
|
||||
|
||||
## Gotchas
|
||||
|
||||
- **API no oficial + rate-limit (429).** pytrends scrapea una API interna de Google que NO es publica. Google la limita agresivamente: rafagas de llamadas devuelven HTTP 429. La funcion reintenta con backoff incremental (5s, 15s, 30s) ante 429; si tras esos reintentos sigue limitada, lanza `RuntimeError` mencionando explicitamente el rate-limit. En entornos de CI/headless es habitual recibir 429 a la primera — no es un bug de la funcion.
|
||||
- **Puede romperse sin aviso.** Al depender de un endpoint interno, Google puede cambiarlo y romper pytrends en cualquier momento. Trata los fallos como esperados y cachea resultados aguas arriba.
|
||||
- **Interes relativo, NO volumen absoluto.** Los valores 0-100 estan normalizados DENTRO del payload consultado (mismo geo + timeframe + conjunto de keywords). 100 = el pico del conjunto, no "100 busquedas". No son comparables entre payloads distintos. Cambiar el set de keywords reescala todos los valores.
|
||||
- **"Breakout" en rising.** Google marca como la cadena literal `"Breakout"` (en vez de un %) las related_queries rising cuyo crecimiento supera ~5000%. Para mantener la columna `value` numerica en Postgres se mapea al sentinel `BREAKOUT_SENTINEL = 999999`. Si necesitas distinguir un breakout real de un valor 999999 legitimo (imposible en la practica para %), filtra por ese sentinel.
|
||||
- **Maximo 5 keywords por payload.** Limite de Google Trends. Pasar mas keywords hace que pytrends falle o ignore las extra. Trocea en lotes de <=5 y llama varias veces (espaciando para no disparar el 429).
|
||||
- **DataFrames vacios.** `interest_over_time()` puede volver vacio (keyword sin datos en la ventana) y `related_queries()` devuelve un dict `{keyword: {'top': df|None, 'rising': df|None}}` con valores None. La funcion maneja ambos casos sin petar: simplemente no genera filas para esas combinaciones.
|
||||
- **Columna `isPartial`.** `interest_over_time()` incluye una columna `isPartial` que marca el ultimo punto como provisional. Se ignora por completo (solo se leen las columnas que coinciden con las keywords).
|
||||
Reference in New Issue
Block a user