e1e9bb7499
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5.4 KiB
5.4 KiB
name, kind, lang, domain, version, purity, signature, description, tags, uses_functions, uses_types, returns, returns_optional, error_type, imports, params, output, tested, tests, test_file_path, file_path
| name | kind | lang | domain | version | purity | signature | description | tags | uses_functions | uses_types | returns | returns_optional | error_type | imports | params | output | tested | tests | test_file_path | file_path | |||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| scrape_google_trends | function | py | datascience | 1.0.0 | impure | def scrape_google_trends(keywords: list[str], geo: str = "ES", timeframe: str = "now 7-d", include_related: bool = True) -> list[dict] | 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. |
|
false | error_go_core |
|
|
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). | false | python/functions/datascience/scrape_google_trends.py |
Ejemplo
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
RuntimeErrormencionando 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 columnavaluenumerica en Postgres se mapea al sentinelBREAKOUT_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) yrelated_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 columnaisPartialque marca el ultimo punto como provisional. Se ignora por completo (solo se leen las columnas que coinciden con las keywords).