Steam Scraper Tutorial: Cómo Recopilar Datos Públicos de Tiendas de Juegos
TL;DR
Los métodos de la API web de Steam, las interfaces de la tienda y el HTML de la tienda tienen diferentes contratos y condiciones de acceso.
Este proyecto combina un ejemplo documentado de una API de noticias con un importador de rastreador de precios ejecutable para datos autorizados.
Los precios de los juegos y las IDs de las aplicaciones proporcionadas son datos sintéticos. No son ofertas reales observadas en Steam.
Compara precios solo dentro de la misma ID de aplicación, región, moneda, tipo de paquete y contexto de observación.
Ausente, no disponible, gratuito y pagado son estados separados; nunca conviertas un precio ausente en cero.
Lo que construirás: Un raspador de datos de juegos de Steam
Construirás un pequeño flujo de trabajo de datos de juegos con dos caminos: recuperar noticias a través de un método documentado de la API web de Steam y normalizar un conjunto de datos de precios permitidos en CSV, JSON y SQLite.
El rastreador de precios se ejecuta localmente con un dato sintético, por lo que todo el camino de análisis y almacenamiento es reproducible sin raspar una tienda en vivo. Para precios de producción, conecta una fuente cuyos términos de acceso y uso de datos cubran tu flujo de trabajo. Esta distinción es importante porque una URL de tienda accesible no es automáticamente una API de precios públicos soportada.
Fuentes de datos de Steam: API de la tienda, API web de Steam y HTML
La recopilación de datos de Steam comienza eligiendo la interfaz que realmente suministra los campos requeridos y permite el uso previsto.
Elegir la fuente de datos de Steam adecuada
Fuente
Propósito adecuado
Límite importante
API web de Steam documentada
Métodos documentados específicos, como noticias de aplicaciones
No todos los campos de la tienda o precios están expuestos
Descubre Nstproxy Crawl - Empieza Tu Prueba Gratuita Hoy
Interfaz de editor/socio aprobada
Datos dentro del derecho del desarrollador
Las credenciales y acceso a la aplicación pueden estar restringidos
Conjunto de datos de precios licenciado
Historia de ofertas regionales bajo contrato
La cobertura y redistribución dependen de la licencia
JSON de cara a la tienda
Detalle potencial de implementación del sitio
La accesibilidad no es una garantía de estabilidad o permiso
HTML de la tienda
Investigación aprobada a nivel de página
Reglas de acceso, estado regional, marcado y trampas de edad
La visión general de la API web de Valve describe el uso de la API documentada. La interfaz de detalles de aplicaciones de la tienda frecuentemente referenciada no debe ser representada como una API de precios general con las mismas garantías documentadas.
Entendiendo las IDs de aplicaciones de Steam y la fijación de precios regional
Una ID de aplicación identifica una aplicación, que puede ser un juego, DLC, demo u otro tipo de aplicación. Una oferta también puede involucrar paquetes o bundles, por lo que una etiqueta a nivel de aplicación no es una identidad comercial completa.
ID de la aplicación de la tienda, tipo de oferta, región, moneda, monto original y actual, estado del precio, fuente y tiempo de observación. Preserva los montos de la fuente como enteros con una convención de unidad explícita. No dividas cada moneda por 100 sin verificar la definición de unidad de la fuente.
Requisitos previos y configuración del entorno Python
El rastreador proporcionado utiliza la biblioteca estándar de Python. Crea un directorio que contenga steam_tracker.py y steam_prices_fixture.json, luego utiliza un entorno virtual.
El fixture contiene nombres y precios de juegos ficticios, incluidos estados pagados, gratuitos y no disponibles. Existe para validar el comportamiento; no lo utilices como una muestra de historial de mercado.
Paso 1: Obtener detalles del juego de Steam
Obtén solo a través de una interfaz que cubra los datos y uso solicitados. Para un ejemplo documentado y específico, el método GetNewsForApp de Valve devuelve noticias de la aplicación utilizando una ID de aplicación y un conteo de resultados limitado.
El rastreador incluye este comando opcional:
python steam_tracker.py --news570
Esta solicitud basada en documentación no se ejecutó como una prueba en vivo de Steam para el artículo. Recupera noticias en lugar de precios, nombres de desarrolladores o un catálogo de productos autoritativo. La distinción evita que una respuesta de noticias sea etiquetada incorrectamente como metadatos completos de la tienda.
Para detalles del juego y precios, importa una respuesta de fuente permitida a través de un adaptador que se mapea en el esquema a continuación.
Paso 2: Extraer metadatos y precios del juego
El esquema normalizado mantiene valores desconocidos explícitos.
Para datos reales, también preserva el tipo de aplicación, la identidad del paquete, la localidad de la fuente y la definición de unidad de monto del proveedor. Los nombres de los desarrolladores, las fechas de lanzamiento y los géneros deben permanecer como nulos cuando están ausentes. Una cadena de fecha de lanzamiento mostrada no siempre es una fecha ISO ordenable.
El analizador rechaza precios gratuitos inconsistentes y estados de precios desconocidos con montos numéricos. Una oferta regional no disponible tiene precios nulos en lugar de un cero fabricado.
Paso 3: Recopilar Múltiples Juegos de Steam
Aplica prácticas de colección limitadas y utiliza una lista de permitidos de App IDs y registra cada resultado. Mantén los IDs inválidos, las ofertas no disponibles en la región, los errores de origen y los precios faltantes por separado.
Al utilizar una fuente en línea aprobada, comparte un presupuesto de tarifas entre los trabajadores y almacena en caché los metadatos estables. No interpretes una recomendación de concurrencia universal como permiso para exceder los límites de un método.
El ejemplo procesa tres registros locales. Aumenta el tamaño del dispositivo para probar el análisis y el almacenamiento antes de agregar un adaptador de adquisición en vivo.
Paso 4: Exportar Datos de Steam a CSV y JSON
CSV es útil para revisión; JSON preserva valores nulos y tipos de campo más claramente. SQLite soporta observaciones históricas.
El colector completo escribe las tres salidas:
"""Analiza un feed de precios autorizado/local; opcionalmente llama a la API pública de noticias documentada."""import argparse
import csv
import json
import sqlite3
import time
from datetime import datetime
from pathlib import Path
from urllib.parse import urlencode
from urllib.request import Request, urlopen
defnormalize(item): appid =int(item["appid"])if appid <=0:raise ValueError("ID de aplicación inválido") observed = item["observed_at"]if datetime.fromisoformat(observed.replace("Z","+00:00")).utcoffset()isNone:raise ValueError("El tiempo de observación debe incluir zona horaria") state = item["price_state"]if state notin("paid","free","unavailable","undisclosed"):raise ValueError("Estado de precio desconocido") initial, final = item.get("initial_minor"), item.get("final_minor") currency, region = item.get("currency"), item["region"]if state in("paid","free"):ifnot currency orany(type(v)isnotintor v <0for v in(initial, final)):raise ValueError("Precio comparable faltante")if state =="free"and(initial !=0or final !=0):raise ValueError("El precio gratuito debe ser cero")elif initial isnotNoneor final isnotNone:raise ValueError("Los precios desconocidos deben permanecer nulos")returndict(appid=appid, name=item["name"], region=region, currency=currency, initial_minor=initial, final_minor=final, price_state=state, observed_at=observed, source=item["source"])defsave(rows, database):with sqlite3.connect(database)as db: db.execute("""CREATE TABLE IF NOT EXISTS prices(
appid INTEGER,name TEXT,region TEXT,currency TEXT,
initial_minor INTEGER,final_minor INTEGER,price_state TEXT,
observed_at TEXT,source TEXT,
PRIMARY KEY(appid,region,observed_at,source))""") columns =list(rows[0]) db.executemany("INSERT OR REPLACE INTO prices VALUES(?,?,?,?,?,?,?,?,?)",[tuple(row[k]for k in columns)for row in rows])defnews(appid): query = urlencode(dict(appid=appid, count=3, maxlength=200,format="json")) request = Request("https://api.steampowered.com/ISteamNews/GetNewsForApp/v2/?"+ query, headers={"User-Agent":"GameResearchDemo/1.0"})with urlopen(request, timeout=20)as response: payload = json.load(response) data = payload.get("appnews",{})ifint(data.get("appid",-1))!= appid:raise ValueError("Respuesta de noticias inesperada")return data.get("newsitems",[])if __name__ =="__main__": parser = argparse.ArgumentParser() parser.add_argument("--fixture", default="steam_prices_fixture.json") parser.add_argument("--db", default="steam.sqlite") parser.add_argument("--news",type=int) args = parser.parse_args()if args.news:print(json.dumps(news(args.news), ensure_ascii=False, indent=2))else: rows =[normalize(item)for item in json.loads(Path(args.fixture).read_text())]ifnot rows:raise SystemExit("No hay registros") save(rows, args.db) Path("steam_prices.json").write_text(json.dumps(rows, indent=2))withopen("steam_prices.csv","w", newline="")as handle: writer = csv.DictWriter(handle, fieldnames=list(rows[0])) writer.writeheader() writer.writerows(rows)print(f"registros_aceptados={len(rows)}")
Mantén las cadenas de precio formateadas como valores de visualización opcionales. Usa montos numéricos normalizados y moneda para comparaciones. Nunca infieras la moneda solo por la ubicación o el idioma del usuario.
Paso 5: Agregar Manejo de Errores y Limitación de Tarifas
Maneja IDs de aplicación inválidos, respuestas no JSON, errores HTTP, tiempos de espera, regiones no disponibles y campos faltantes como fallos o estados explícitos.
El ejemplo realiza una solicitud de noticias limitada y se detiene en caso de error. Un adaptador de fuente aprobada en producción debería agregar un pequeño presupuesto de reintentos para fallos transitorios, honrar Retry-After y evitar reintentar fallos de permiso. No se garantiza que ninguna tasa de solicitud sea aceptable en todas las interfaces de Steam.
Paso 6: Raspar Páginas de la Tienda Steam Cuando las APIs Son Insuficientes
Utiliza HTML solo donde tu acuerdo de acceso lo permita. Verifica si los campos estructurados están presentes en el documento antes de lanzar un navegador.
Desarrolla el analizador contra HTML autorizado guardado y prueba los casos de precio ausente, juego gratuito, DLC y no disponible regionalmente. No eludas la verificación de edad, los requisitos de inicio de sesión o la denegación explícita. Si el acceso al precio no está aprobado, utiliza un conjunto de datos con licencia o una interfaz de socio apropiada.
El Acuerdo de Suscripción de Valve incluye restricciones de automatización. Los términos de API web rigen el uso de API; deben revisarse por separado del comportamiento de la tienda.
Paso 7: Programar el Monitoreo de Precios de Steam
Programa de acuerdo con el permiso y los requisitos de frescura de la fuente elegida, utilizando un pipeline de monitoreo de precios documentado. Un flujo de datos aprobado diario puede ser suficiente para un panel de investigación; no proporciona ejecución de precios en el momento de la transacción.
Almacena observaciones con hora UTC e identidad de la fuente. Calcula un cambio solo entre ofertas comparables. Alerta sobre un cambio de moneda inesperado o una oferta faltante en lugar de llamarlo un descuento.
Ejemplo de Raspar Steam: Construir un Rastreador de Precios de Juegos
Ejecuta el accesorio incluido, inspecciona tres registros normalizados y confirma que el registro gratuito permanece en cero mientras que el registro no disponible permanece nulo.
Para detectar un cambio de precio, consulta las dos últimas observaciones aceptadas para la misma app, región, moneda, fuente y tipo de oferta. Compara los montos finales solo cuando ambos tienen estados de precio válidos. Agrega una tabla de cambios de solo adición que contenga el monto anterior, el nuevo monto, las marcas de tiempo y las referencias de evidencia.
Las verificaciones locales cubren normalización, manejo de nulos, exportaciones y almacenamiento repetido de la misma instantánea. No establecen la precisión del precio de Steam en vivo o los permisos de interfaz actuales.
Errores Comunes al Raspar Steam y Soluciones
Síntoma
Explicación posible
Tratamiento correcto
Sin precio
Gratuito, no disponible, no divulgado o extracción fallida
Preservar estado distinto e inspeccionar evidencia
Montos diferentes
Desajuste de región/moneda/paquete
Comparar claves de identidad coincidentes
Desarrollador faltante
La fuente no proporciona el campo
Mantener nulo; no inferir
Idioma cambiado
Cambiado de localidad o sesión
Almacenar localidad con la observación
Respuesta vacía
ID no válido, problema de método o fallo de fuente
Mantener fallo fuera de observaciones aceptadas
Juego “gratis” repentino
Valor faltante forzado a cero
Corregir validación y reparar registros afectados
Raspar Steam a Gran Escala: Arquitectura y Costos
Para implementación en producción, separa descubrimiento, metadatos estables, ofertas en cambio, normalización e informes. Caché campos estables, actualiza solo el cohorte de ofertas aprobado y persiste trabajos fallidos con reintentos limitados.
Presupuesta datos licenciados, solicitudes, renderización donde sea necesario, almacenamiento, mantenimiento y revisión de la fuente. Usar Nstdata Crawl para un camino de página aprobado puede proporcionar infraestructura de adquisición; no suministra derechos de datos específicos de Steam o un esquema de precios garantizado.
Confirma permiso de interfaz, términos de API, atribución, caché, redistribución y condiciones de uso comercial antes de la implementación. No extiendas la disponibilidad de un método a la autorización para recopilar datos de usuario no relacionados.
Mantén los datos personales de los jugadores fuera de un proyecto de precios de la tienda a menos que sea explícitamente necesario y apropiadamente autorizado. La investigación de precios de productos no requiere perfiles de jugadores o actividad de cuentas.
Lista de Verificación Final del Proyecto
Valida IDs de aplicaciones e identidades de ofertas, preserva el contexto regional, distingue entre pérdidas y gratuitos, prueba exportaciones, confirma la persistencia de instantáneas y revisa los términos de acceso. Conecta una fuente de precio en vivo solo después de que el importador local y el acuerdo de uso de datos estén verificados.
Valida el contenido de la tienda permitido
Mantén la adquisición aprobada separada del análisis específico de juegos y derechos de fuente.
Sí. Valve documenta los métodos de la API web de Steam, pero eso no implica un punto de precio general soportado para cada uso.
Q: ¿Cómo puedo obtener los precios de los juegos de Steam?
Utiliza una interfaz aprobada o una fuente licenciada que cubra los campos, regiones y usos que necesites. Este proyecto normaliza esa entrada y la prueba con un dispositivo.
Q: ¿El ejemplo contiene precios reales de juegos?
No. Los registros de precios suministrados y los ID de aplicación son sintéticos, claramente etiquetados como datos de prueba.
Q: ¿Puedo rastrear descuentos?
Sí, si la fuente permite el monitoreo y los registros de ofertas comparables están disponibles. Mantén consistentes la moneda, región, paquete y marcas de tiempo.
Q: ¿Por qué no se utiliza appdetails como el contrato de tutorial en vivo?
Un punto final orientado a la tienda no debe presentarse como una API de precios general completamente documentada y autorizada simplemente porque es accesible.
Q: ¿Puede el método de noticias documentado reemplazar la fuente de precios?
No. Las noticias y los precios de la tienda son conjuntos de datos diferentes y deben mantener esquemas y permisos separados.
Lena Zhou
Oct. 19th 2026
Rastrea sitios web completos con una sola solicitud API
Convierte cualquier sitio web en Markdown, HTML, JSON, enlaces, PDF y más, sin gestionar infraestructura de rastreo.
99,8% de éxito con renderizado JavaScript
Obtén datos limpios, listos para LLM, en múltiples formatos