Puppeteer 关闭 javascript 警告框

ast*_*ine 4 node.js puppeteer

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

我刚开始尝试 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();
});
Run Code Online (Sandbox Code Playgroud)

这是我得到的错误:UnhandledPromiseRejectionWarning: E​​rror: Node is not visible or not an HTMLElement at ElementHandle._clickablePoint

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

Md.*_*her 9

该页面上的内容很少,

  • 警报框仅在页面加载后加载(它onloadbody标签上有一个属性)。所以你应该等到网络空闲。
  • 由于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
);
Run Code Online (Sandbox Code Playgroud)

2.点击之前等待元素

已经建议其他答案,等待元素使用waitFor.

// wait and click the alert button
await page.waitFor("#BoxAlertBtnOk");
await page.click("#BoxAlertBtnOk");
Run Code Online (Sandbox Code Playgroud)

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
});
Run Code Online (Sandbox Code Playgroud)

4. 使用page.evaluateanddocument.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()
);
Run Code Online (Sandbox Code Playgroud)

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);
      }
    });
  });
}
Run Code Online (Sandbox Code Playgroud)

最终代码:

为了清楚起见,这里是我如何使用上面指定的所有代码片段。

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();
});
Run Code Online (Sandbox Code Playgroud)

结果:

它完美无缺!

笔记:

注意我是如何同时使用 new Promise 和 async await 的。这可能不是最佳实践,但现在您已经知道在为一些旧网站创建抓取工具时要寻找的内容。

  • 太棒了!谢谢你,我确实欠你一杯咖啡。只是一件事,我看到当我运行脚本时,它会打开我的 Chronium 并显示正在执行的操作...默认情况下不是隐藏的吗? (2认同)

OrA*_*yag 6

如果它与面临对话框的其他人相关,下面的代码为我解决了这个问题:

    this.page.on('dialog', async dialog => {
        await dialog.dismiss();
    });
Run Code Online (Sandbox Code Playgroud)