使用Puppeteer获取ul下li的innerText时报未处理Promise拒绝错误如何解决
报错原因排查
- DOM节点无法跨环境序列化:
page.evaluate()是在浏览器沙箱环境执行的,返回值需要是可序列化为JSON的普通数据类型,你直接将原生DOM元素存入数组返回,Puppeteer无法将DOM节点从浏览器环境传递到Node.js主进程,直接抛出异常导致Promise被拒绝,没有错误捕获逻辑就触发了未处理Promise拒绝的报错。 - 变量拼写错误:return语句中将
following误写为followinf,浏览器环境执行时会抛出未定义变量异常,也会导致Promise被拒绝。 - 空值调用风险:如果页面结构变动、元素未完成渲染导致
querySelector()匹配结果为null,后续调用getElementsByTagName会直接抛出空指针异常。 - 需求匹配错误:你的目标是获取li的innerText数组,但现有代码是直接存储li元素对象,和预期需求不符。
修正后的完整代码
const puppeteer = require('puppeteer'); (async () => { const browser = await puppeteer.launch({ headless: 'new' }); // 适配新版本Puppeteer的无头模式 const page = await browser.newPage(); const giturl = 'https://github.com/siddhart1o1'; await page.goto(giturl, { waitUntil: 'networkidle2' }); try { let data = await page.evaluate(() => { // 加空值兜底,避免选择器匹配失败报错 const getText = (selector) => document.querySelector(selector)?.innerText || ''; const stars = getText('#js-pjax-container > div.container-xl.px-3.px-md-4.px-lg-5 > div > div.flex-shrink-0.col-12.col-md-3.mb-4.mb-md-0 > div > div.js-profile-editable-replace > div.d-flex.flex-column > div.js-profile-editable-area.d-flex.flex-column.d-md-block > div.flex-order-1.flex-md-order-none.mt-2.mt-md-0 > div > a:nth-child(3) > span'); const followers = getText('#js-pjax-container > div.container-xl.px-3.px-md-4.px-lg-5 > div > div.flex-shrink-0.col-12.col-md-3.mb-4.mb-md-0 > div > div.js-profile-editable-replace > div.d-flex.flex-column > div.js-profile-editable-area.d-flex.flex-column.d-md-block > div.flex-order-1.flex-md-order-none.mt-2.mt-md-0 > div > a:nth-child(1) > span'); const following = getText('#js-pjax-container > div.container-xl.px-3.px-md-4.px-lg-5 > div > div.flex-shrink-0.col-12.col-md-3.mb-4.mb-md-0 > div > div.js-profile-editable-replace > div.d-flex.flex-column > div.js-profile-editable-area.d-flex.flex-column.d-md-block > div.flex-order-1.flex-md-order-none.mt-2.mt-md-0 > div > a:nth-child(2) > span'); const repos = getText('#js-pjax-container > div.container-xl.px-3.px-md-4.px-lg-5 > div > div.flex-shrink-0.col-12.col-md-9.mb-4.mb-md-0 > div.UnderlineNav.user-profile-nav.d-block.d-md-none.position-sticky.top-0.pl-3.ml-n3.mr-n3.pr-3.color-bg-primary > nav > a:nth-child(2) > span'); // 处理年份列表,直接取innerText const yearListUl = document.querySelector('div.js-profile-timeline-year-list.color-bg-primary.js-sticky > ul'); const yearTextArray = []; if (yearListUl) { const liList = yearListUl.getElementsByTagName('li'); for (let i = 0; i < liList.length; i++) { yearTextArray.push(liList[i].innerText.trim()); } } return { stars, followers, following, // 修正拼写错误 repos, yearTextArray } }); console.log(data); } catch (err) { // 捕获evaluate执行阶段的所有错误,避免未处理的Promise拒绝 console.error('数据抓取失败:', err); } await browser.close(); })();
核心修改点说明
- 新增了
getText工具方法加空值兜底,避免选择器匹配失败抛出异常 - 遍历li节点时直接提取
innerText存入数组,返回的是纯文本数组,可正常跨环境序列化 - 修正了
followinf的拼写错误 - 外层新增
try/catch捕获执行阶段的所有异常,不会出现未处理Promise拒绝的报错 - 优化了无头模式配置,适配新版本Puppeteer的语法规范
内容的提问来源于stack exchange,提问作者Ishaan
相关产品推荐
相关产品推荐

