Puppeteer爬虫for循环提取数据存入MongoDB变量未定义报错如何解决
错误原因
你遇到的报错核心来自两个问题:
page.evaluate()的代码运行在浏览器沙箱环境中,和你的Node.js运行环境完全隔离,你在回调内部定义的nameElement等变量,外部Node代码无法访问,直接调用就会触发未定义报错- 存库逻辑和数据提取逻辑脱离,你把数据提取写在浏览器端循环里,没有把提取结果传回Node层,存库时也只能尝试存储单条数据,无法覆盖循环里的所有条目
修复方案
你需要把page.evaluate()内部提取的所有数据组装成数组返回给Node层,再遍历数组批量存入MongoDB,修改后的代码如下:
const kclResults = []; async function scrapeInfiniteScrollItems( page, scrollDelay = 10000 ) { try { // 浏览器端提取数据,最终返回所有结果数组到Node层 const scrapedList = await page.evaluate(async () => { const elements = Array.from(document.querySelectorAll("[role='listitem'] ._2DX0iPG8PDF3Si_o5PlzIj")); const result = []; for (let i = 0; i < elements.length; i++) { elements[i].click(); // 点击后如果需要等待内容加载可以加延时:await new Promise(r => setTimeout(r, 500)) // 提取字段加兜底逻辑,避免匹配不到元素报错 const nameElement = document.querySelector("[data-log-name='PersonName']")?.textContent || ''; const emailElement = document.querySelector("[data-log-name='Email']")?.textContent || ''; const allElements = document.querySelector("[aria-label='Contact information']")?.textContent || ''; const officeLocation = document.querySelector("[data-log-name='OfficeLocation']")?.textContent || ''; const position = document.querySelector("[data-log-name='Company']")?.textContent || ''; const jobTitle = document.querySelector("[data-log-name='JobTitle']")?.textContent || ''; const departament = document.querySelector("[data-log-name='Department']")?.textContent || ''; // 单条数据存入结果数组 result.push({ nameElement, emailElement, allElements, officeLocation, position, jobTitle, departament }); } return result; }); // 遍历提取结果批量存库 for (const item of scrapedList) { const kclResult = new KingsDB(item); await kclResult.save(); // 存库是异步操作,加await避免逻辑混乱 kclResults.push(kclResult); } console.log(kclResults); return kclResults; } catch (error) { console.log(error); } }
注意事项
- 浏览器沙箱环境中无法访问Node层加载的cheerio,所以代码里替换成了原生DOM操作,如果目标页面自带jQuery可以继续用
$选择器 - 如果点击条目后信息加载有延迟,可以在click逻辑后加适当的等待时间,保证字段能正常提取到
内容的提问来源于stack exchange,提问作者Christopher
相关产品推荐
相关产品推荐

