【问题标题】:Can't locate and click on a terms of conditions button无法找到并单击条件条款按钮
【发布时间】:2022-10-13 23:14:39
【问题描述】:

我是 pupeeteer 的新手,首先我要做的是加载一个页面并单击一个按钮。但是,它无法定位元素。我认为这是因为我需要找到父元素或父元素的父元素。

<button role="button" data-testid="uc-accept-all-button" class="sc-gsDKAQ fHGlTM" style="border: 2px solid rgb(247, 196, 0); padding: 0.375rem 1.125rem; margin: 0px 6px;">Accept All</button>

这是从检查中获取的完整 css 选择器

#focus-lock-id > div.sc-furwcr.lhriHG > div > 
div.sc-bYoBSM.egarKh > div > div > div.sc-dlVxhl.bEDIID > 
div > button:nth-child(3)

这是我的代码:

const puppeteer = require("puppeteer");

async function launch() {
  const browser = await puppeteer.launch({
    headless: false,
    defaultViewport: false,
  });
  const page = await browser.newPage();

  await page
    .goto("", {
      waitUntil: "networkidle0",
    })
    .catch((err) => console.log("error loading url", err));
  page.click('button[data-testid="uc-deny-all-button"]');
}
launch();

这是一个简单的接受和条件块,我想单击“全部接受”按钮将其关闭并继续进行。我需要先等待父元素然后进一步挖掘什么通常的操作?或者有什么简单的方法?

这是我试图关闭条款和条件的网站:https://www.partslink24.com/

【问题讨论】:

    标签: javascript testing puppeteer browser-automation


    【解决方案1】:

    几个问题:

    1. 选择器在页面加载后动态显示,因此您应该waitForSelector 而不是假设networkidle0 足以捕捉按钮。
    2. 您想要的选择器在影子根中,所以select the root and dip into it with .shadowRoot
    3. 您的.click() 呼叫必须是awaited。
      const puppeteer = require("puppeteer"); // ^18.0.4
      
      let browser;
      (async () => {
        browser = await puppeteer.launch({headless: true});
        const [page] = await browser.pages();
        const url = "https://www.partslink24.com/";
        await page.goto(url, {waitUntil: "domcontentloaded"});
        const rootSel = "#usercentrics-root";
        const btnSel = 'button[data-testid="uc-deny-all-button"]';
        const rootContainer = await page.waitForSelector(rootSel);
        const root = await rootContainer.evaluateHandle(el => el.shadowRoot);
        const btn = await root.waitForSelector(btnSel);
        await btn.click();
        await page.waitForFunction(`
          !document.querySelector("${rootSel}").querySelector('${btnSel}')
        `);
        await page.screenshot({path: "test.png", fullpage: true});
      })()
        .catch(err => console.error(err))
        .finally(() => browser?.close())
      ;
      

    【讨论】:

    • 非常感谢,请问为什么我们在做 waitForFunctions() 我们调用它的时候怎么说,evaluateHandle 也不是很清楚。非常感谢你
    • waitForFunction 用于延迟截图直到按钮消失。也许没有必要,但我想确保没有竞争条件。您可能可以跳过这些行。他们在那里证明代码有效。 evaluateHandle 将影子根的 ElementHandle 返回到节点上下文,因此我可以等待按钮出现在其中。
    • 谢谢大佬,请问右边有登录密码表格之类的输入是否需要等待同意条款div消失才能真正找到输入?等待 page.type('#username', 'username');等待 page.type('#password', 'password');等待 page.click('#submit');等待页面.waitForNavigation();
    • 如果对元素是否存在有任何不确定性,我等待。触发导航时应使用Promise.all pattern
    • 谢谢你,我保证最后一个 :) 我编辑了我的问题,想知道如何在一堆 div 中找到特定元素,我可以简单地说我想要标题是福特的品牌徽标类
    猜你喜欢
    • 2013-08-24
    • 2023-04-08
    • 2022-12-05
    • 2020-10-25
    • 1970-01-01
    • 2019-08-10
    • 1970-01-01
    • 1970-01-01
    • 2021-06-11
    相关资源
    最近更新 更多