Selenium WebDriver如何实现等待超时异常的兜底处理?
解决方案
Selenium WebDriver Node.js 版本的driver.wait()方法没有内置自动执行fallback逻辑的配置项,等待超时后会直接抛出TimeoutError,未捕获该错误就会导致整个进程中断。
循环场景下的正确实现
不要在Promise链式调用的回调里写循环控制语句,回调的独立作用域会导致continue/break这类关键字无法关联到外层循环,直接用try/catch包裹等待逻辑是最稳定、可读性最高的方案:
// 日期遍历循环内的单页处理逻辑 for (const date of targetDateList) { await driver.get(`对应日期的目标页面地址?date=${date}`); let tableElements = null; try { tableElements = await driver.wait( until.elementsLocated(By.css('#myDataTableOfInterest')), 10000 ); } catch (e) { // 只处理等待超时的错误,其他类型错误照常抛出,避免掩盖真实故障 if (e.name === 'TimeoutError') { console.log(`[SKIP] ${date} 站点无可用数据,跳过当前页`); continue; } throw e; } // 表格存在时执行后续数据解析、存储逻辑 const parsedData = await parseTableData(tableElements); writeToFile(date, parsedData); }
效率优化方案
如果站点无数据时会渲染固定的“无有效数据”提示元素,可以不用等满10秒超时,用until.or()组合等待条件,任意一个条件满足就结束等待,大幅缩短无数据页面的等待耗时:
// 定义两个互斥的等待条件 const waitForTable = until.elementsLocated(By.css('#myDataTableOfInterest')); const waitForNoDataTip = until.elementLocated(By.css('.page-no-data')); // 替换为站点实际无数据提示的选择器 for (const date of targetDateList) { await driver.get(`对应日期的目标页面地址?date=${date}`); try { const matchResult = await driver.wait( until.or(waitForTable, waitForNoDataTip), 10000 ); // 判断命中的是哪个条件 if (Array.isArray(matchResult) && await matchResult[0].getTagName() === 'table') { const parsedData = await parseTableData(matchResult); writeToFile(date, parsedData); } else { console.log(`[SKIP] ${date} 站点无可用数据,跳过当前页`); continue; } } catch (e) { // 兜底处理页面加载崩溃、元素异常等极端情况 console.log(`[ERROR] ${date} 页面加载异常: ${e.message}, 跳过`); continue; } }
原有写法失效原因
你之前用.then(successHandler, errorHandler)的写法里,continue关键字写在Promise的错误回调函数内部,作用域属于回调函数本身,和外层的日期循环不在同一个上下文,JS引擎无法识别这是外层循环的控制语句,自然不会生效。
内容的提问来源于stack exchange,提问作者Jonathan Straus
相关产品推荐
相关产品推荐

