Fotos por LUGAR en el panel — Brave Image Search
Fecha: 2026-09-19 · Proyecto: ~/nef/estado_turismo
Script: spab-retrieval/scripts/retrieval-imagenes-lugares.mjs
Datos: spab-retrieval/data/base/imagenes-lugares.json (clave = nombre normalizado)
Por qué Brave y no Google/SerpAPI
- La Places API (New) también da
places.photos, pero es SKU de pago por llamada y requiere proxy para no exponer la llave. - SerpAPI habría que contratarlo y las imágenes son de Google (licencia difusa).
- Brave Image Search ya tiene llave (
BRAVE_SEARCH_API_KEY), devuelvethumbnail.srcproxeado (embebible),properties.url,page_urlysource(dominio) → atribución verificable. Free tier ~1 req/s, 2000/mes.
Pipeline
- Objetivos = todos los lugares de
lugares.csv+ los 35 nombres curados de Ruta Maya (extraídos detren-maya-api.js), deduplicados por nombre normalizado (minúsculas, sin acentos, espacios colapsados). - Una consulta Brave por lugar:
"<nombre> <destino>"(oQuintana Roo, Méxicopara los curados),count=6,safesearch=strict. - Se prefieren dominios de licencia libre/oficial
(Wikimedia, Unsplash, Pexels,
gob.mx,inah.gob.mx, UNESCO). - Se guardan hasta 3 por lugar:
{thumb, url, page, source, titulo}. - Pausa de ~1.1 s entre llamadas + backoff ante 429.
Consumo
- 825 lugares, 2475 imágenes. Se corren por muestra para no quemar cuota:
node scripts/retrieval-imagenes-lugares.mjs 20. - El script hace merge con el JSON existente, así se puede avanzar por lotes.
Integración en el front
- Rutas generadas (Pacífico, Colonial, Sur, Sophia):
generar-rutas.mjsinyectafotosendetail()ythumbenindex(), leyendo el JSON por nombre normalizado. - Ruta Maya:
tren-maya-api.jscargaimagenes-lugares.json, adjunta las fotos endetail()y elthumbenindex(); si no hay, cae al tinte de categoría (placeholder). - El panel (
places-panel.js) pintaphotos: [{url, caption, tint}]en una rejilla de 3 con el dominio comocaption.
Dónde se muestran las imágenes (tres superficies)
- Hero del detalle (
.pp-hero):#fillT2toma la primera foto conurly la pone de fondo; clasehas-photo+ velo inferior para que la etiqueta de categoría se lea. Sin foto → tinte. - Rejilla de fotos (
.pp-photos): hasta 3 fotos del lugar,caption= dominio. - Miniatura de la lista (
.pp-swatch):#buildListpintap.thumb(deindex()); clasehas-photo. Sin thumb → tinte.
Contrato de datos: PlaceIndex.thumb?: string (primera foto) y
PlaceDetail.photos: {url, caption, tint}[].
Fixes de paso en el generador (afectaban a las 4 rutas)
cards()no devolvíatint/vol/summary→c.tint[0]tronaba.index()devolvíacoords:{lat,lng}en vez delng/latplanos →Invalid LngLat object: (NaN, NaN).detail()no devolvíadesc/hours/hist/tags(forma que espera el panel).
Caveat de licencia
Brave devuelve imágenes de terceros (blogs, OTAs, wikis). No todas son de
licencia libre: por eso cada foto muestra su dominio de origen y se prefieren
dominios libres/oficiales. Si se requiere 100% libre, usar Commons (menor
cobertura para comercios) — ver 2026-09-19-imagenes-libres-commons.md.