Skip to content

如何从 Stream 游戏库存页面中获取结构化数据

js
function extractSteamGameInfo(gameElement) {
  // 1. 验证输入是否为有效的 DOM 元素
  if (!gameElement || typeof gameElement.querySelector !== 'function') {
    console.error("输入无效:需要一个 DOM 元素。");
    return null;
  }

  // 2. 辅助函数,安全地在传入的元素内查询和获取信息
  const getText = (selector) => gameElement.querySelector(selector)?.textContent.trim() || null;
  const getAttribute = (selector, attr) => gameElement.querySelector(selector)?.getAttribute(attr) || null;

  // 3. 提取各项信息 (逻辑与之前完全相同,但上下文是 gameElement)

  // 游戏名称 (从 <img> alt 属性获取)
  const name = getAttribute('img', 'alt');

  // 商店链接和 App ID
  const storeUrl = getAttribute('a._1bAC6eBHy0MpRWrwTkgT9o', 'href');
  const appIdMatch = storeUrl ? storeUrl.match(/\/app\/(\d+)/) : null;
  const appId = appIdMatch ? appIdMatch[1] : null;

  // 封面图片
  const imageUrl = getAttribute('img', 'src');
  
  // 游戏时间 (需要移除标签文本)
  const playtimeLabel = getText('._26nl3MClDebGDV7duYjZVn ._2L1rk5AZ6FW8trFciJnHSs');
  const fullPlaytimeText = getText('._26nl3MClDebGDV7duYjZVn');
  const playtime = fullPlaytimeText && playtimeLabel ? fullPlaytimeText.replace(playtimeLabel, '').trim() : fullPlaytimeText;

  // 最后运行日期 (同样移除标签文本)
  const lastPlayedLabel = getText('._2jglu-fYE_XNY6tkn6J99Y ._2L1rk5AZ6FW8trFciJnHSs');
  const fullLastPlayedText = getText('._2jglu-fYE_XNY6tkn6J99Y');
  const lastPlayed = fullLastPlayedText && lastPlayedLabel ? fullLastPlayedText.replace(lastPlayedLabel, '').trim() : fullLastPlayedText;

  // 成就进度
  const achievementsText = getText('._1YRRMk6X7vrOL-02K-q1pf'); // "32/32"
  let achievements = { earned: 0, total: 0 };
  if (achievementsText) {
    const parts = achievementsText.split('/');
    if (parts.length === 2) {
      achievements = {
        earned: parseInt(parts[0], 10),
        total: parseInt(parts[1], 10),
      };
    }
  }

  // 是否是完美游戏 (检查特定SVG元素是否存在)
  const isPerfect = !!gameElement.querySelector('div[title="获得了所有可能的成就"]');
  
  // 安装大小
  const installedSize = getText('._2zfId9cfT2zTYc0lGKOhrr');

  // 4. 组装成一个对象返回
  return {
    name,
    appId,
    playtime,
    lastPlayed,
    achievements,
    isPerfect
  };
}

function getGameDivItems () {
  return document.querySelector('[data-featuretarget="gameslist-root"] .Panel[style*="height"]').childNodes
}

function extractSteamGameInfoAll () {
  const gameDivItems = getGameDivItems()
  return [...gameDivItems].map(extractSteamGameInfo).filter((item) => item.achievements?.earned)
}

console.log(extractSteamGameInfoAll())