Puppeteer调用frameset第5层子页面外部JS函数报create_order未定义问题
错误原因
你遇到的ReferenceError: create_order is not defined报错,核心原因是create_order()函数定义在多层嵌套的子frame的独立window作用域下,你当前的代码直接在顶层页面的执行上下文调用该函数,顶层window对象下没有挂载这个方法,因此触发未定义错误。
可行解决方案
你需要先定位到目标子frame的实例,所有和这个frame相关的操作都要在该frame的执行上下文内完成,具体实现逻辑如下:
- 先实现递归查找子frame的工具函数,匹配到包含目标操作元素的子frame
// 递归遍历所有层级的frame,返回符合匹配规则的frame实例 async function findTargetFrame(root, matcher) { for (const frame of root.frames()) { if (await matcher(frame)) return frame const child = await findTargetFrame(frame, matcher) if (child) return child } return null }
- 在完成店铺选择、frameset加载完成后,调用工具函数定位目标frame,再执行点击操作:
// 等待店铺选择后页面跳转、frameset加载完成 await page.waitForNavigation({ waitUntil: 'networkidle2' }) // 匹配包含「Create New Shopping Basket」链接的目标frame const targetFrame = await findTargetFrame(page, async (frame) => { try { // 等待目标元素加载完成,避免 frame 未加载完全导致匹配失败 await frame.waitForSelector('a::-p-text("Create New Shopping Basket")', { timeout: 3000 }) return true } catch { return false } }) if (!targetFrame) throw new Error('未找到承载购物篮操作的子框架') // 方案1:模拟手动点击链接(兼容性最好,完全对齐手动操作逻辑) await targetFrame.click('a::-p-text("Create New Shopping Basket")') // 方案2:如果需要直接调用JS函数,在目标frame的上下文内执行即可 // await targetFrame.evaluate(() => create_order())
额外优化建议
如果你要操作的frame有固定的name或者id属性,可以直接通过page.frames().find(frame => frame.name() === '你的frame名')匹配,不需要递归遍历,执行效率更高。
内容的提问来源于stack exchange,提问作者scorpiux
相关产品推荐
相关产品推荐

