循环调用NightmareJS爬取Gartner评论出现ERR_ABORTED报错如何解决
NightmareJS批量爬取Gartner评论解决方案
错误原因
ERR_ABORTED错误核心由两类问题导致:
- 普通同步for循环不会等待Nightmare的异步操作(点击、页面加载、数据抓取)完成就触发下一轮调用,多个导航请求并发触发导致前序请求被强制中断
- 使用
li:nth-child(N)选择器时,会把ul下的span、div等非li子元素计入排序,导致选中的不是实际的第N条评论,甚至选中不可点击元素触发异常导航
实现思路
使用异步串行的for...of循环配合await保证每一步操作完成后再执行下一轮,同时将选择器替换为li:nth-of-type(N)仅匹配li元素,跳过ul下的杂元素,保证每次点击的是有效评论节点。
可运行代码示例
const Nightmare = require('nightmare') const cheerio = require('cheerio') // 复用单个Nightmare实例,不要在循环内重复创建减少开销 const nightmare = Nightmare({ show: true }) const targetUrl = 'https://www.gartner.com/reviews/market/unified-communications-as-a-service-worldwide/vendor/ringcentral/product/ringcentral-office/reviews' async function crawlTop2Reviews() { const crawlResult = [] try { // 打开评论列表页,等待评论容器加载完成 await nightmare .goto(targetUrl) .wait('ul.reviews-list') // 替换为实际的评论列表ul选择器 .wait(1000) // 预留动态内容渲染时间 // 遍历前2条评论 for (const index of [1, 2]) { // 仅匹配第index个li元素,跳过ul下的span、div等杂元素 const currentReviewSelector = `ul.reviews-list li:nth-of-type(${index})` // 点击评论进入详情/展开详情 await nightmare .click(currentReviewSelector) .wait('.review-detail-container') // 替换为实际的评论详情容器选择器 .wait(500) // 提取短描述与长描述 const reviewInfo = await nightmare.evaluate(() => { const $ = cheerio.load(document.documentElement.innerHTML) // 替换为实际的短描述、长描述选择器 const shortDescription = $('.review-title').text().trim() const fullDescription = $('.review-full-content').text().trim() return { shortDescription, fullDescription } }) crawlResult.push(reviewInfo) // 关闭详情弹窗/返回列表页,等待列表重新加载完成 await nightmare .click('.close-review-btn') // 替换为实际的关闭按钮/返回按钮选择器 .wait('ul.reviews-list') .wait(500) } console.log('前2条评论抓取完成:', crawlResult) return crawlResult } catch (error) { console.error('抓取异常:', error) } finally { // 销毁实例释放资源 await nightmare.end() } } crawlTop2Reviews()
注意事项
- 代码中所有占位的选择器请替换为实际调试得到的Gartner页面对应元素选择器
- 优先使用
wait(元素选择器)等待目标元素渲染完成,不要完全依赖固定时长等待,避免页面加载速度差异导致报错 - 所有Nightmare操作都需要加
await保证串行执行,不要并发触发多个导航请求
内容的提问来源于stack exchange,提问作者vijayakumarpsg587
相关产品推荐
相关产品推荐

