Appearance
如何从 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())