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
相关产品推荐
相关产品推荐

