无法使用 puppeteer 点击 cookie 按钮

问题描述 投票:0回答:1

我正在尝试关闭网站上的 cookie 横幅/模式,在我看来,单击按钮和带有 puppeteer 的标签元素对我不起作用。 Cookie 横幅/模式始终保留在我拍摄的屏幕截图中。此外,当我记录按钮或使用 if 条件时,它会找到它。似乎是点击本身的问题,而不是找到元素。我尝试了多种方法。我尝试调试这个问题好几天了,但我无法弄清楚。

这是我的代码。网站 Makeup.uk 只是一个例子,我的网站是捷克语的,所以我不想让人们感到困惑。

const puppeteer = require("puppeteer");

(async function main() {
  try {
    const browser = await puppeteer.launch({
      headless: true,
      defaultViewport: {
        width: 1920,
        height: 1080,
      },
    });
    const page = await browser.newPage();

    const response = await page.goto("https://makeup.uk/", {
      waitUntil: ["domcontentloaded", "networkidle2"],
    });

    // first way, doesn't work
    const xp = '::-p-xpath("//button[contains(text(), "Accept")]")';
    const el = await page.waitForSelector(xp);
    await el.click();

    // second way, doesn't work
    const buttons = await page.$$('::-p-xpath("//button")');
    for (const button of buttons) {
      let text = await button.evaluate((el) => el.textContent);
      if (text.includes("Accept")) {
        console.log("Found my button!"); //This logs in the console!
        await button.evaluate((b) => b.click());
      }
    }

const date = new Date().toTimeString();
    await page.screenshot({ path: date + ".png", fullPage: true });
    await browser.close();
  }

    catch (err) {
      console.error(err);
    }
  })();

如果我从终端中的第一种方式记录

el
,它会说

el CdpElementHandle {
  handle: CdpJSHandle {},
  [Symbol(_isElementHandle)]: true
}

我理解为 - 我找到了该元素。

我尝试了多种其他方法,例如在 page.evaluate() 中找到它,我什至不记得还有什么,结果是相同的。每次我找到该按钮时,只需单击就不会执行任何操作。每次屏幕截图中都会出现 Cookie 横幅。其他网站也一样,不仅仅是这个网站。

我的 puppeteer 版本是这个(也尝试了最新的)

"puppeteer": "^22.4.1"

javascript puppeteer
1个回答
0
投票

尽管不鼓励使用 XPath,但您的选择器对我来说工作正常。

'::-p-xpath("//button")'
可以简单地作为 CSS 选择器
'button'
。请参阅这篇文章,了解 Puppeteer 中更好的文本选择。

关闭后,横幅动画会逐渐向下,因此,如果它没有在屏幕截图中及时完成,您仍然会看到它。

在测试环境之外的浏览器自动化中,没有义务像人类一样行事。摆脱横幅的一种非动画方法是简单地使用 JS 将其立即从 DOM 中炸掉:

const puppeteer = require("puppeteer"); // ^22.7.1

const url = "<Your URL>";

(async function main() {
  let browser;

  try {
    browser = await puppeteer.launch({
      defaultViewport: {
        width: 1920,
        height: 1080,
      },
    });
    const [page] = await browser.pages();
    const response = await page.goto(url, {waitUntil: "networkidle2"});
    const banner = await page.waitForSelector(".cookie-notice");
    await banner.evaluate(el => el.remove());
    const path = new Date().toISOString() + ".png";
    await page.screenshot({path, fullPage: true});
  } catch (err) {
    console.error(err);
  }
  finally {
    await browser?.close();
  }
})();

在其他网站上,请记住横幅可能位于 iframe 或影子根中,因此预计这不是适用于任何横幅的灵丹妙药。

在另一个站点上,如果

.remove()
没有触发所需的事件,并且您被迫单击按钮,则可以使用
page.waitForFunction
进行轮询,直到该元素从 DOM 中删除或隐藏,作为另一种应对方式点击后有动画。

有关代码的其他注释:

  • ["domcontentloaded", "networkidle2"]
    可以简单地称为
    "networkidle2"
    "domcontentloaded"
    保证在
    "networkidle2"
    解决时解决。
  • 通常避免使用元素句柄,除非您需要可信事件进行测试。对于抓取,只需使用不受信任的 DOM 点击,这比受信任的点击更可靠。
© www.soinside.com 2019 - 2024. All rights reserved.