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

Cypress爬虫脚本处理无价格元素问题求助

Cypress爬虫跳过不可用商品的问题解决

问题场景

开发了一款Cypress网页爬虫脚本,用于抓取电商网站的商品标题与价格:

  • 正常商品显示价格元素(类名:.sc-dqia0p-3)
  • 不可用商品不显示价格元素,而是展示提示元素:
    <div 
      data-testid="product-block-unavailable-text" 
      class="sc-bcdv5e-9 hMrYQF"
      >Ovaj proizvod više nije dostupan</div>
    

需求:当Cypress无法找到价格元素时,不触发元素不存在的报错,而是检查上述不可用元素后跳过该商品。但现有代码中,cy.get('.sc-dqia0p-3').eq(index)会直接因元素不存在报错,无法执行后续的不可用检查逻辑。

原代码片段:

// Scrape the loaded products
cy.get('.sc-y4jrw3-7').each((productName, index, list) => {
    // Check if the product is unavailable
    cy.get('.sc-dqia0p-3').eq(index).then((priceElement) => {
        // Check if the price element is available
        if (Cypress.$(priceElement).length > 0) {
            const title = productName.text().trim();
            let price = priceElement.text().trim();

            // Append "din" to the price
            price = `${price} din`;

            // Store product data in the products array
            products.push({ title, price });
        } else {
            // Check if the product is unavailable
            cy.get('.sc-bcdv5e-9').eq(index).then((unavailableElement) => {
                const unavailableText = unavailableElement.text().trim();
                if (unavailableText === 'Ovaj proizvod više nije dostupan') {
                    cy.log(`Product ${index + 1} is unavailable. Skipping...`);
                } else {
                    cy.log(`Product element at index ${index} not found or unavailable. Skipping...`);
                }
            });
        }
    });
});

问题原因

Cypress的cy.get()命令默认会断言目标元素必须存在,如果找不到元素会直接抛出错误并终止当前命令链,因此else分支永远无法被执行。此外,使用全局的.eq(index)匹配价格/不可用元素,容易因页面元素顺序变化导致匹配错误。

解决方案

针对每个商品容器进行独立查询,避免全局索引匹配的问题,同时使用Cypress.$()直接在DOM中查询元素(不会触发Cypress的存在断言),或者在商品容器内使用cy.find()结合条件判断:

方案1:基于商品容器的DOM查询(推荐)

假设每个商品的标题、价格/不可用元素都在同一个父容器内,先获取商品容器列表,再逐个处理:

// 替换为实际页面的商品容器选择器
cy.get('.product-container').each((productContainer, index) => {
    const $container = Cypress.$(productContainer);
    const title = $container.find('.sc-y4jrw3-7').text().trim();

    // 查询当前商品的价格元素
    const $priceElement = $container.find('.sc-dqia0p-3');
    if ($priceElement.length > 0) {
        let price = $priceElement.text().trim();
        price = `${price} din`;
        products.push({ title, price });
    } else {
        // 查询不可用提示元素(优先用data-testid定位更稳定)
        const $unavailableElement = $container.find('[data-testid="product-block-unavailable-text"]');
        if ($unavailableElement.length > 0) {
            const unavailableText = $unavailableElement.text().trim();
            if (unavailableText === 'Ovaj proizvod više nije dostupan') {
                cy.log(`Product ${index + 1} is unavailable. Skipping...`);
            } else {
                cy.log(`Product ${index + 1} has unknown unavailable status. Skipping...`);
            }
        } else {
            cy.log(`Product ${index + 1} has neither price nor unavailable text. Skipping...`);
        }
    }
});

方案2:使用Cypress命令链的错误捕获

如果必须沿用原有的全局元素查询逻辑,可以通过catch()捕获元素不存在的错误,执行后续检查:

cy.get('.sc-y4jrw3-7').each((productName, index) => {
    const title = productName.text().trim();

    // 尝试查找价格元素,关闭日志避免干扰
    cy.get('.sc-dqia0p-3').eq(index, { log: false }).then((priceElement) => {
        let price = priceElement.text().trim();
        price = `${price} din`;
        products.push({ title, price });
    }).catch(() => {
        // 价格元素不存在时,检查不可用提示
        cy.get('[data-testid="product-block-unavailable-text"]').eq(index, { log: false }).then((unavailableElement) => {
            const unavailableText = unavailableElement.text().trim();
            if (unavailableText === 'Ovaj proizvod više nije dostupan') {
                cy.log(`Product ${index + 1} is unavailable. Skipping...`);
            } else {
                cy.log(`Product ${index + 1} has unknown status. Skipping...`);
            }
        }).catch(() => {
            cy.log(`Product ${index + 1} has no valid elements. Skipping...`);
        });
    });
});

关键说明

  • 优先使用商品容器的局部查询($container.find()),比全局的.eq(index)更可靠,避免页面元素顺序变化导致的匹配错误。
  • Cypress.$()直接操作DOM,不会触发Cypress的断言逻辑,适合做元素存在性检查。
  • 若使用Cypress命令链,需通过catch()捕获元素不存在的错误,或者添加{ timeout: 0 }参数快速判断元素是否存在。

内容的提问来源于stack exchange,提问作者No Tools No Craft

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 18:53:23