Puppeteer将page.evaluate()调用提取到函数后执行失败的问题求助
大家好,我最近在用Puppeteer写代码时碰到了一个奇怪的问题——原本正常运行的代码,把page.evaluate()的调用提取到单独函数后就直接报错了,想请各位帮忙分析下原因~
原本能正常运行的代码
let ele = await page.waitForSelector(".selector") let attributeValue = page.evaluate((x) => x.getAttribute("attribute-name"), ele)
重构后报错的代码
function getAttribute(ele, attributeName) { return page.evaluate((x) => x.getAttribute(attributeName), ele) } let ele = await page.waitForSelector(".selector") let attributeValue = await getAttribute(ele, "attribute-name")
出现的错误信息
Error [ReferenceError]: attributeName is not defined
at evaluate (evaluate at getAttribute (file:///Users/user/projects/puppeteer-issue/index.js:17:15),:0:23)
at #evaluate (file:///Users/user/projects/puppeteer-issue/node_modules/puppeteer-core/lib/esm/puppeteer/common/ExecutionContext.js:249:19)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async ExecutionContext.evaluate (file:///Users/user/projects/puppeteer-issue/node_modules/puppeteer-core/lib/esm/puppeteer/common/ExecutionContext.js:146:16)
at async file:///Users/user/projects/puppeteer-issue/index.js:21:23
我自己琢磨了下,猜测问题出在page.evaluate()的回调函数运行环境上——这个lambda函数是在浏览器的上下文里执行的,而不是Node.js的上下文,所以attributeName这个变量根本传不到浏览器那边,导致浏览器找不到它才报了错。
修复后的可行代码
后来我调整了参数传递的方式,把attributeName也作为参数传给page.evaluate的回调,问题就解决了:
function getAttribute(ele, attributeName) { // 将attributeName作为第二个参数传入,让浏览器上下文能拿到它 return page.evaluate((x, attrName) => x.getAttribute(attrName), ele, attributeName) } let ele = await page.waitForSelector(".selector") let attributeValue = await getAttribute(ele, "attribute-name")
简单解释下:Puppeteer的page.evaluate()方法,第一个参数是要在浏览器里运行的函数,后面跟着的参数会被序列化后传递给这个函数,这样浏览器上下文就能获取到这些参数的值了。之前的写法里,回调直接引用了Node.js上下文里的attributeName,但浏览器那边根本访问不到这个变量,所以才会抛出未定义的错误。
备注:内容来源于stack exchange,提问作者dQw4w9WyXcQ

