You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Puppeteer中捕获新窗口弹窗的Alert消息?

解决Puppeteer捕获新窗口Alert消息的问题

核心问题分析

你的代码中dialog事件绑定时机过晚:在等待到popup页面后才绑定dialog事件,但此时Alert可能已经触发完毕,导致事件监听器无法捕获到消息。此外,popup.on("dialog")不需要用await修饰,事件绑定是同步操作。

修正方案

方案1:监听浏览器全局Dialog事件

由于新窗口的Alert属于浏览器全局的Dialog事件,直接在Browser实例上监听dialog事件可以确保不会错过任何弹窗,无论弹窗来自哪个页面。

修改后的代码:

const puppeteer = require('puppeteer');

(async () => {
    const browser = await puppeteer.launch({ headless: false, slowMo: 50 });
    const page = await browser.newPage();
    
    await page.goto('http://www.rbmtest.com.co/AdminMenuMonWeb/pages/welcome/Login.jsp', { waitUntil: "networkidle0" });

    try {
        // 提前监听浏览器全局的dialog事件
        let dialogMsg = null;
        const dialogPromise = new Promise(resolve => {
            browser.once('dialog', async dialog => {
                dialogMsg = dialog.message();
                console.log('捕获到Alert消息:', dialogMsg);
                await dialog.accept();
                resolve();
            });
        });

        // 监听新窗口弹出
        const newPagePromise = new Promise(tab => page.once('popup', tab));

        // 输入账号密码(错误示例)
        await page.type('#login', 'jhonsmith');
        await page.type('#password', 'France5523*!');

        // 点击提交按钮
        await page.click('input[name="b1"]');

        // 等待新窗口和dialog事件完成
        const popup = await newPagePromise;
        await dialogPromise;

        // 根据是否捕获到错误消息处理逻辑
        if (dialogMsg) {
            // 登录失败:写入数据库逻辑
            console.log('登录失败,错误消息:', dialogMsg);
        } else {
            // 登录成功:等待页面元素验证后写入数据库
            await popup.waitForXPath('//*[@id="as_cssmenu"]/ul/li[1]/a', { timeout: 5000 });
            console.log('登录成功');
        }

        await popup.close();
        await page.close();

    } catch (error) {
        console.log('执行错误:', error);
        await page?.close();
    }

    await browser.close();

})();

方案2:提前绑定Popup页面的Dialog事件

如果需要仅针对新窗口监听Dialog,可以在等待Popup的同时,通过targetcreated事件提前获取页面实例并绑定事件,避免绑定时机过晚:

const puppeteer = require('puppeteer');

(async () => {
    const browser = await puppeteer.launch({ headless: false, slowMo: 50 });
    const page = await browser.newPage();
    
    await page.goto('http://www.rbmtest.com.co/AdminMenuMonWeb/pages/welcome/Login.jsp', { waitUntil: "networkidle0" });

    try {
        let dialogMsg = null;
        let popupPage = null;

        // 监听targetcreated事件,提前获取新页面并绑定dialog事件
        const newPagePromise = new Promise(resolve => {
            browser.on('targetcreated', async target => {
                if (target.type() === 'page' && target.url() !== page.url()) {
                    popupPage = await target.page();
                    // 立即绑定dialog事件
                    popupPage.once('dialog', async dialog => {
                        dialogMsg = dialog.message();
                        console.log('捕获到Alert消息:', dialogMsg);
                        await dialog.accept();
                    });
                    resolve(popupPage);
                }
            });
        });

        // 输入账号密码
        await page.type('#login', 'jhonsmith');
        await page.type('#password', 'France5523*!');

        // 点击提交
        await page.click('input[name="b1"]');

        // 等待新页面加载
        await newPagePromise;

        // 处理登录结果
        if (dialogMsg) {
            console.log('登录失败');
            // 写入数据库逻辑
        } else {
            await popupPage.waitForXPath('//*[@id="as_cssmenu"]/ul/li[1]/a', { timeout: 5000 });
            console.log('登录成功');
            // 写入数据库逻辑
        }

        await popupPage.close();
        await page.close();

    } catch (error) {
        console.log('执行错误:', error);
        await page?.close();
    }

    await browser.close();

})();

关键注意事项

  • 事件绑定时机:必须在触发弹窗的操作(点击提交按钮)之前,完成Dialog事件的监听绑定。
  • Dialog事件的异步性:Dialog事件是异步触发的,需要用Promise等待事件完成后再进行后续逻辑判断。
  • 避免重复监听:使用once替代on监听事件,防止多次触发导致逻辑混乱。

内容的提问来源于stack exchange,提问作者Smith Brown

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 06:24:22