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

如何正确解析CSV供Puppeteer读取UPC并填充到网站输入框爬取图书数据

问题原因

1. CSV分隔符配置错误

你提供的CSV样例是*逗号(,)*作为字段分隔符,但你代码中调用csv-parser时指定的分隔符是冒号:,导致CSV解析逻辑无法正确拆分字段,拿不到CODECONTENT列的有效值,最终读取到的UPC数组是空值或者全为NaN。

2. 不必要的数值类型转换

你在读取CODECONTENT时加了+号强制转为数值类型:rows.push(+row.CODECONTENT),UPC是13位编码,部分特殊场景可能开头带0,转为数值会丢失前置0,导致后续搜索匹配失败。

3. 价格获取逻辑冗余

你写的finally块会强制覆盖try和catch中得到的newprice值,前面的价格判断逻辑完全失效,属于多余代码。


修复方案

第一步:修正CSV解析逻辑

把readCsvAsync调用时的分隔符改为逗号,,同时去掉强制转数值的+号:

async function upcData() {
    try {
        // 把分隔符从':'改为','
        const rows = await readCsvAsync('Book_Bulk.csv', ',');
        return rows;
    } catch (err) {
        console.log(err);
        return [];
    }
}

// 同时修改readCsvAsync中的push逻辑,去掉+号
function readCsvAsync(filename, delimiter=',', encoding='utf-8') {
    return new Promise((resolve, reject) => {
        const rows = [];
        try {
            fs.createReadStream(filename, {encoding: encoding})
                .pipe(parse({delimiter: delimiter}))
                // 去掉+号,保留字符串格式的UPC
                .on('data', (row) => rows.push(row.CODECONTENT))
                .on('end', () => resolve(rows))
                .on('error', reject);
        } catch (err) {
            reject(err);
        }
    });
}

第二步:优化爬取逻辑

每次搜索前清空输入框,避免上一次的UPC残留,同时删除多余的finally块:

async function getpageData(page,upc){
    await page.goto('https://www.bookdepository.com/');
    const searchInput = '#book-search-form > div.el-wrap.header-search-el-wrap > input.text-input';
    await page.waitForSelector(searchInput);
    // 先清空输入框再填入新UPC
    await page.$eval(searchInput, input => input.value = '');
    await page.type(searchInput, upc);
    await page.click('#book-search-form > div.el-wrap.header-search-el-wrap > button');
    
    // 原有字段获取逻辑不变,仅修改价格部分:
    let newprice = '无定价';
    try {
        await page.waitForSelector('div.price.item-price-wrap.hidden-xs.hidden-sm > span.sale-price', { timeout: 1500 });
        const price = await page.$eval('div.price.item-price-wrap.hidden-xs.hidden-sm > span.sale-price', span => span.innerText);
        newprice = price.slice(-6);
    } catch {
        try {
            await page.waitForSelector('p.list-price', { timeout: 1500 }); 
            const price = await page.$eval('p.list-price', p => p.innerText);
            newprice = price.slice(-6);
        } catch {}
    }

    return {
        title: title,
        author: author,
        genre: genre,
        format: format,
        publisher: publisher,
        year: newyear,
        price: newprice
    }
}

第三步:增加异常处理避免单条UPC爬取失败中断整个流程

修改main函数中的循环逻辑,增加try catch包裹单条爬取逻辑:

async function main(){
    const allupcs = await upcData();
    // 先打印UPC数组确认解析结果
    console.log('解析到的UPC列表:', allupcs);
  
    const browser = await puppeteer.launch({ headless: false, defaultViewport: null, args: ['--start-maximized']});
    const page = await browser.newPage();
    const scrapedData = [];

    for(let upc of allupcs){
        if(!upc) continue; // 跳过空的UPC
        try {
            const data = await getpageData(page,upc);
            scrapedData.push({upc, ...data});
            console.log(`UPC ${upc} 爬取完成`);
        } catch (e) {
            console.log(`UPC ${upc} 爬取失败:`, e.message);
            // 失败后等待2秒再继续,避免触发反爬
            await page.waitForTimeout(2000);
        }
    }

    console.log('全部爬取结果:', scrapedData);
    await browser.close();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 16:54:04