如何使用Puppeteer点击target=_blank按钮打开并控制新标签页
问题原因分析
- 原监听逻辑没有过滤target类型,浏览器的
targetcreated事件会响应所有新建目标(包括iframe、浏览器扩展后台页、资源请求目标等),如果在点击按钮前刚好有其他目标创建,监听逻辑会提前返回非预期的无效对象 - 原代码没有等待
target.page()异步执行完成就直接resolve,部分场景下新标签页还未完成初始化,target.page()会返回null或者未就绪的页面对象 - 拿到
page2后没有等待页面加载完成就直接执行后续操作,也会导致操作失效
修复后可稳定运行的代码
// 等待按钮可见且可点击 await page1.waitForSelector('#button', { visible: true }); const link = await page1.$('#button'); // 优化新标签页监听逻辑,过滤有效页面、等待页面对象初始化完成 const newPagePromise = new Promise(resolve => { browser.on('targetcreated', async target => { // 只处理页面类型的新目标,过滤iframe等其他目标 if (target.type() === 'page') { const newPage = await target.page(); resolve(newPage); // 拿到有效页面对象后移除监听,避免重复触发 browser.removeAllListeners('targetcreated'); } }); }); // 点击按钮触发新标签页打开,增加100ms延迟避免点击事件未被正常捕获 await link.click({ button: 'left', delay: 100 }); const page2 = await newPagePromise; // 等待新页面加载完成,默认等待load事件,也可根据需求改为'domcontentloaded'或'networkidle2' await page2.waitForLoadState(); await page2.bringToFront();
补充说明
- 如果按钮绑定的是自定义JS逻辑生成跳转地址,可在点击前增加
await page1.waitForTimeout(50)的逻辑,确保动态地址生成完成再触发点击 - 整套逻辑不会影响原有page1的状态,符合不关闭第一个页面的要求
内容的提问来源于stack exchange,提问作者KarmaX JenJen
相关产品推荐
相关产品推荐

