【问题标题】:Puppeteer close javascript alert boxPuppeteer 关闭 javascript 警报框
【发布时间】:2020-10-28 22:39:30
【问题描述】:

我正在尝试单击this website 上的页面按钮,但是当我进入该站点时会出现一个警告框,我不知道如何关闭它。

我刚开始尝试 Puppeteer,这是我现在使用的简单代码:

const ptr = require('puppeteer');

ptr.launch().then(async browser => {

const page = await browser.newPage();

await page.setViewport({ width: 1280, height: 800 });
await page.goto('https://portaleperiti.grupporealemutua.it/PPVET/VetrinaWebPortalePeriti/');

//This is the alert button selector 
await page.click("#BoxAlertBtnOk");

//This is the button on the page i want to click on 
await page.click("input[value='Perito RE / G.F.']");

await page.screenshot({
    path: 'screenshot.png',
    fullPage: true
});

await browser.close();
});

这是我得到的错误:UnhandledPromiseRejectionWarning:错误:节点不可见或不是 HTMLElement 在 ElementHandle._clickablePoint

任何帮助将不胜感激,谢谢!

【问题讨论】:

  • 这可能就是你要找的东西:github.com/GoogleChrome/puppeteer/blob/master/docs/…
  • 我看到了,但我认为它适用于浏览器对话框而不适用于 javascript 对话框? (按照网站链接查看警告框)
  • 看来我误解了你所说的“警报框”。警报框通常是由 Javascript 触发的浏览器元素。您是在谈论 DOM 警报框/模态框/弹出框吗?
  • 抱歉,我写了警告框,因为他们在站点选择器上是这样称呼它的。是的,我说的是警报框/模式
  • 我想问题是当您尝试单击它时尚未出现警告框。您应该等待它使用此方法出现:github.com/GoogleChrome/puppeteer/blob/master/docs/…

标签: node.js puppeteer


【解决方案1】:

该页面上发生的事情很少,

  • 警告框仅在页面加载后加载(它在body 标记上有一个onload 属性)。所以你应该等到网络空闲。
  • 由于window.open() 代码放入onclick 处理程序,因此单击这些“Perito”按钮会创建一个新窗口/选项卡。
  • 如果用户尚未登录,新选项卡会多次重定向并显示登录页面。

解决方案:

1。确保正确加载页面。

只需将{ waitUntil: "networkidle0" } 添加到.goto.waitForNavigation

await page.goto(
    "https://portaleperiti.grupporealemutua.it/PPVET/VetrinaWebPortalePeriti/",
    { waitUntil: "networkidle0" }
    // <-- Make sure the whole page is completely loaded
);

2。等待元素再点击

已经在其他答案上提出了建议,等待使用waitFor的元素。

// wait and click the alert button
await page.waitFor("#BoxAlertBtnOk");
await page.click("#BoxAlertBtnOk");

3。可选,在点击按钮后在截屏前添加几秒钟。

// optional, add few seconds before taking this screenshot
// just to make sure it works even on slow machine
await page.waitFor(2000);
await page.screenshot({
  path: "screenshot_before.png",
  fullPage: true
});

4。使用page.evaluatedocument.querySelector 获取元素

page.click 不会处理所有类型的点击。有时,某些元素绑定了不同的事件,您必须单独处理。

// we can click using querySelector and the native
// just page.click does not trigger the onclick handler on this page
await page.evaluate(() =>
    document.querySelector("input[value='Perito RE / G.F.']").click()
);

5。单独处理新标签

browser.once('targetcreated')new Promisebrowser.pages() 一起,您可以捕获新创建的选项卡并对其进行处理。

注意:在使用之前阅读答案末尾的最终代码。

// this is the final page after clicking the input on previous page
// https://italy.grupporealemutua.it/FIM/sps/IDPRMA/saml20/login
function newTabCatcher(browser) {
  // we resolve this promise after doing everything we need to do on this page
  // or in error
  return new Promise((resolve, reject) => {
    // set the listener before clicking the button to have proper interaction
    // we listen for only one new tab
    browser.once("targetcreated", async function() {
      console.log("New Tab Created");
      try {
        // get the newly created window
        const tabs = await browser.pages();
        const lastTab = tabs[tabs.length - 1];

        // Wait for navigation to finish as well as specific login form
        await Promise.all([
          lastTab.waitForNavigation({ waitUntil: "networkidle0" }),
          lastTab.waitFor("#div_login")
        ]);

        // browser will switch to this tab just when it takes the screenshot
        await lastTab.screenshot({
          path: "screenshot_newtab.png",
          fullPage: true
        });

        resolve(true);
      } catch (error) {
        reject(error);
      }
    });
  });
}

最终代码:

为了清楚起见,这里是我使用上面指定的所有代码 sn-ps 的方式。

const ptr = require("puppeteer");

ptr.launch({ headless: false }).then(async browser => {
  const page = await browser.newPage();

  await page.setViewport({ width: 1280, height: 800 });
  await page.goto(
    "https://portaleperiti.grupporealemutua.it/PPVET/VetrinaWebPortalePeriti/",
    { waitUntil: "networkidle0" }
    // <-- Make sure the whole page is completely loaded
  );

  // wait and click the alert button
  await page.waitFor("#BoxAlertBtnOk");
  await page.click("#BoxAlertBtnOk");

  // optional, add few seconds before taking this screenshot
  // just to make sure it works even on slow machine
  await page.waitFor(2000);
  await page.screenshot({
    path: "screenshot_before.png",
    fullPage: true
  });

  // we can click using querySelector and the native
  // just page.click does not trigger the onclick handler on this page
  await page.evaluate(() =>
    document.querySelector("input[value='Perito RE / G.F.']").click()
  );

  // here we go and process the new tab
  // aka get screenshot, fill form etc
  await newTabCatcher(browser);

  // rest of your code
  // ... 

  await browser.close();
});

结果:

完美运行!

注意:

注意我是如何一起使用 new Promise 和 async await 的。这可能不是最佳做法,但现在您可以了解在为一些旧网站创建抓取工具时要查找的内容。

【讨论】:

  • 这太完美了!谢谢,我确实欠你一杯咖啡。只是一件事,我看到当我运行脚本时,它会打开我的 Chronium 并显示正在做什么……默认情况下不隐藏?
  • 啊,我忘了删除headless: false,通常我在调试任何此类问题时使用它来查看实际发生了什么。总比瞎了好多了。您可以设置headless: true 或删除它。
  • 如果我删除它或将其设置为 true,它不会保存新选项卡中的屏幕截图(或 newTabCatcher 不运行)
  • 我明白了。所以这是另一个问题。那么,无头浏览器肯定不适合您的脚本。创建另一个问题,我会花时间调试那个问题。 :) 有时在无头模式下做很多事情是不可能的。
  • 实际上我正在截屏以查看我的代码是否正常工作,我只是想输入登录表单,然后在那里抓取元素......你认为这样可以吗? (无头假)
【解决方案2】:

您的按钮 - #BoxAlertBtnOk 稍后会出现在网页上,当您调用 await page.click("#BoxAlertBtnOk"); 时,该按钮是不可见的。尝试等到它可见然后采取行动:

await page.waitForSelector("#BoxAlertBtnOk");
await page.click("#BoxAlertBtnOk");

await page.waitForSelector("input[value='Perito RE / G.F.']");
await page.click("input[value='Perito RE / G.F.']");

【讨论】:

  • @astronomy-domine 可能错误已被下一行代码抛出。我更新了我的答案。
  • 如果我添加另一个选择器,它不会给出错误,但截取的屏幕截图仍然打开警报框。只是好像不能点击。
【解决方案3】:

如果它与其他面对对话框的人有关,以下代码为我解决了它:

    this.page.on('dialog', async dialog => {
        await dialog.dismiss();
    });

【讨论】:

    猜你喜欢
    • 2010-10-02
    • 1970-01-01
    • 2014-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-11
    • 1970-01-01
    相关资源
    最近更新 更多