You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Steam交易卡价格爬取返回大量undefined问题求助

问题排查与解决方案

一、大量undefined的原因及修复

核心原因分析

  1. 文本提取逻辑错误:原代码中$('.normal_price').text()会拼接所有匹配元素的文本,导致后续split(' ')[3]无法准确定位价格;且部分页面的文本结构与预期不符,索引3不存在时直接返回undefined。
  2. 部分游戏无交易卡:不是所有Steam游戏都支持交易卡,这类游戏的市场页面没有价格元素,自然无法提取有效数据。
  3. 高频请求被拦截:循环发起大量异步请求触发Steam反爬机制,部分请求返回异常页面,无价格信息。
  4. Cookie有效性问题:Cookie过期或格式错误时,请求会返回未登录状态页面,无法加载正确价格。

代码修复要点

1. 修正价格提取逻辑

只获取第一个匹配的价格元素文本,避免多元素文本拼接混乱;同时增加容错逻辑,用正则兜底提取价格:

function filterTradingCard(gameId){
    var options = {
        'method': 'GET',
        'url': `https://steamcommunity.com/market/search?q=&category_753_Game%5B%5D=tag_app_${gameId}&category_753_cardborder%5B%5D=tag_cardborder_0&category_753_item_class%5B%5D=tag_item_class_2&appid=753#p1_price_asc`,
        'headers': {
            'Cookie': `webTradeEligibility=${webTradeEligibility}; browserid=${browserid}; steamLoginSecure=${steamLoginSecure}; sessionid=${sessionid}`
        }
    };

    request(options, (error, response, html)=> {
        if (error) {
            console.error(`游戏ID ${gameId} 请求失败:`, error);
            return;
        }
        if (response.statusCode !== 200){
            console.log(`游戏ID ${gameId} 响应错误: ${response.statusCode}`);
            return;
        }
        
        const $ = cheerio.load(html);
        // 只取第一个价格元素,避免多元素文本拼接
        const priceElement = $('.normal_price').first();
        if (!priceElement.length) {
            console.log(`游戏ID ${gameId} 无交易卡`);
            return;
        }
        const rawPriceText = priceElement.text().trim();
        
        // 优先按空格分割取价格,失败则用正则匹配
        let pricePart = rawPriceText.split(' ')[2];
        if (!pricePart) {
            const priceMatch = rawPriceText.match(/\d+,\d+/);
            pricePart = priceMatch ? priceMatch[0] : undefined;
        }

        if (!pricePart) {
            console.log(`游戏ID ${gameId} 价格解析失败: ${rawPriceText}`);
            return;
        }
        
        // 转换为数值并输出
        const numericPrice = convertPriceToNumber(pricePart);
        console.log(`游戏ID ${gameId} 交易卡价格: ${numericPrice} ARS`);
    })
}

2. 控制请求并发

将请求包装为Promise,限制并发数量并增加请求间隔,避免触发反爬:

const requestPromise = require('request-promise');

// 改写为返回Promise的异步函数
async function filterTradingCard(gameId){
    var options = {
        'method': 'GET',
        'url': `https://steamcommunity.com/market/search?q=&category_753_Game%5B%5D=tag_app_${gameId}&category_753_cardborder%5B%5D=tag_cardborder_0&category_753_item_class%5B%5D=tag_item_class_2&appid=753#p1_price_asc`,
        'headers': {
            'Cookie': `webTradeEligibility=${webTradeEligibility}; browserid=${browserid}; steamLoginSecure=${steamLoginSecure}; sessionid=${sessionid}`
        }
    };

    try {
        const html = await requestPromise(options);
        const $ = cheerio.load(html);
        const priceElement = $('.normal_price').first();
        if (!priceElement.length) return null;
        
        const rawPriceText = priceElement.text().trim();
        let pricePart = rawPriceText.split(' ')[2] || rawPriceText.match(/\d+,\d+/)[0];
        return convertPriceToNumber(pricePart);
    } catch (error) {
        console.error(`游戏ID ${gameId} 请求失败:`, error);
        return null;
    }
}

// 批量处理游戏ID,控制并发
async function getInfo(){
    try {
        const html = await requestPromise('https://store.steampowered.com/search/?sort_by=Price_ASC&maxprice=840&category1=998&category2=29');
        const $ = cheerio.load(html);

        const gameIds = [];
        $('.col.search_capsule').each(function(i,element) { 
            let gameId = $(this).find('img').attr('src').split("/")[5].trim();
            gameIds.push(gameId);
        });

        // 每次并发2个请求,间隔500ms
        const concurrency = 2;
        for (let i = 0; i < gameIds.length; i += concurrency) {
            const batch = gameIds.slice(i, i + concurrency);
            const results = await Promise.all(batch.map(id => filterTradingCard(id)));
            batch.forEach((id, index) => {
                if (results[index]) {
                    console.log(`游戏ID ${id} 交易卡价格: ${results[index]} ARS`);
                }
            });
            await new Promise(resolve => setTimeout(resolve, 500));
        }
    } catch (error) {
        console.error("获取游戏列表失败:", error);
    }
}

async function getList(){
  await getInfo();
}

getList();

二、价格转数值实现

通过正则提取价格中的数字部分,替换逗号为小数点后转换为数值:

function convertPriceToNumber(priceStr) {
    if (!priceStr) return null;
    // 匹配带逗号的小数格式
    const match = priceStr.match(/(\d+,\d+)/);
    if (match) {
        return parseFloat(match[0].replace(',', '.'));
    }
    return null;
}

内容的提问来源于stack exchange,提问作者Lucas Genovese

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 04:25:16