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

Puppeteer中如何精准选中同时含body-copy与custom-body-copy的类?

问题

需要在Puppeteer中精准选中同时拥有body-copy和custom-body-copy类的元素(页面存在数百个body-copy类元素),对应的HTML结构如下:

<div class="row item-row" id="1000017509" data-body-row="" automation-id="itemRows_17">
    <div class="body-copy custom-body-copy" automation-id="itemNumberLabel_17">
           Item&nbsp;879520
    </div>
</div>

当前使用的代码如下:

const products = await page.$$('.item-row'); 

Promise.all(products.map(async product => {
    // 查找产品SKU、名称和价格
    let productId = await product.$eval('.body-copy', el => el.innerText.trim().replace(/,/g, '').replace('Item', '').replace(/\s+/g, ''));
    // 如需产品名称,可使用:let productName = await product.$eval(".body-copy-link", el => el.innerText.trim().replace(/,/g,' -'));
    let productPrice = await product.$eval('.product_desc_txt div span', el => el.innerText.trim().replace(/,/g, ''));

    // 格式化为CSV行
    return productId + ',' + productPrice + ',';
})).then(lines => {
    // 写入文件
    fs.writeFileSync("products.csv", lines.join('\n'), 'utf-8');
    browser.close();

将选择器改为.body-copy.custom-body-copy时,会抛出错误Error: failed to find element matching selector "${selector}",但该选择器在document.querySelectorAll()中可正常使用,请问该如何解决?

解决方法

1. 处理部分父容器无目标元素的情况

代码遍历所有.item-row并在其中查找目标元素,但可能存在部分.item-row内部没有同时拥有两个类名的元素,导致$eval因找不到元素抛出错误。而控制台的document.querySelectorAll是全局查找,不会遍历每个父容器,因此不会触发该问题。

解决方式:

  • 先尝试获取元素,存在再执行逻辑:
let productId = '';
const skuEl = await product.$('.body-copy.custom-body-copy');
if (skuEl) {
  productId = await skuEl.evaluate(el => el.innerText.trim().replace(/,/g, '').replace('Item', '').replace(/\s+/g, ''));
}
  • 或用try/catch捕获错误:
let productId = '';
try {
  productId = await product.$eval('.body-copy.custom-body-copy', el => el.innerText.trim().replace(/,/g, '').replace('Item', '').replace(/\s+/g, ''));
} catch (e) {
  console.log(`当前行找不到目标元素: ${e}`);
  // 可选择跳过当前项或设默认值
}

2. 等待动态元素加载完成

若页面为异步加载,执行page.$$('.item-row')时部分元素的类名可能还未更新为body-copy custom-body-copy,需增加等待逻辑:

// 等待至少一个目标元素加载完成
await page.waitForSelector('.item-row .body-copy.custom-body-copy');
const products = await page.$$('.item-row'); 

或在遍历每个父容器时等待内部元素:

await product.waitForSelector('.body-copy.custom-body-copy', { timeout: 3000 });
let productId = await product.$eval('.body-copy.custom-body-copy', el => el.innerText.trim().replace(/,/g, '').replace('Item', '').replace(/\s+/g, ''));

3. 更换选择器方式验证

若问题仍存在,可尝试其他选择器写法:

// 精确匹配类名顺序
await product.$eval('[class="body-copy custom-body-copy"]', el => ...);
// 匹配包含指定类名的元素
await product.$eval('.body-copy[class*="custom-body-copy"]', el => ...);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 12:17:08