为何在Puppeteer的page.$$eval中无法返回Set类型?
Puppeteer返回Set时得到空对象的原因及解决办法
问题场景
以下代码运行正常,控制台能输出页面链接的数组:
import puppeteer from "puppeteer" const browser = await puppeteer.launch({ headless: false }) const page = await browser.newPage() await page.goto("https://www.scrapethissite.com/pages/") let result = await page.$$eval("body a", (data) => { let links = data.map((elem) => elem.href) return links }) console.log(result)
但将回调函数的返回值改为Set对象后,控制台输出的却是空对象{}:
import puppeteer from "puppeteer" const browser = await puppeteer.launch({ headless: false }) const page = await browser.newPage() await page.goto("https://www.scrapethissite.com/pages/") let result = await page.$$eval("body a", (data) => { let links = data.map((elem) => elem.href) return new Set(links) // 此处修改为返回Set }) console.log(result) // 输出{}
原因解析
核心问题在于Puppeteer的跨上下文数据传输机制:$$eval的回调函数运行在浏览器的页面上下文,而返回值需要传递到Node.js的主上下文,这个过程会对数据做JSON序列化处理。
但Set属于JavaScript的内置复杂类型,JSON格式并不支持直接序列化Set对象,Puppeteer尝试序列化时,只能得到一个空对象。
解决方法
方法1:将Set转为数组后返回
数组是JSON支持的类型,可以正常完成跨上下文传输,回到Node.js上下文后再重新生成Set:
import puppeteer from "puppeteer" const browser = await puppeteer.launch({ headless: false }) const page = await browser.newPage() await page.goto("https://www.scrapethissite.com/pages/") let result = await page.$$eval("body a", (data) => { let links = data.map((elem) => elem.href) return Array.from(new Set(links)) // 把Set转成数组返回 }) // 在Node.js侧重新创建Set const uniqueLinks = new Set(result) console.log(uniqueLinks)
方法2:在浏览器上下文完成逻辑,返回序列化兼容数据
如果不需要在浏览器侧保留Set结构,可以直接在回调里完成去重等逻辑,返回普通数组或对象:
// 示例:直接返回去重后的数组 let result = await page.$$eval("body a", (data) => { return [...new Set(data.map(elem => elem.href))] }) console.log(result)
内容的提问来源于stack exchange,提问作者Noob
相关产品推荐
相关产品推荐

