puppeteer:如何等到元素可见?

IT技术 javascript node.js google-chrome-devtools puppeteer
2021-03-14 13:14:18

我想知道我是否可以告诉 puppeteer 等到显示元素。

const inputValidate = await page.$('input[value=validate]');
await inputValidate.click()
        
// I want to do something like that 
waitElemenentVisble('.btnNext ')

const btnNext = await page.$('.btnNext');
await btnNext.click();

有什么办法可以做到这一点吗?

6个回答

我认为您可以page.waitForSelector(selector[, options])为此目的使用函数。

const puppeteer = require('puppeteer');

puppeteer.launch().then(async browser => {
  const page = await browser.newPage();
  page
    .waitForSelector('#myId')
    .then(() => console.log('got it'));
    browser.close();
});

要检查可用的选项,请参阅github 链接。

@joy,你​​可以使用page.waitFor它的用途非常广泛
2021-04-27 13:14:18
这是一个很好的答案?代码片段甚至没有进入网页!
2021-04-30 13:14:18
@shafeen 我建议对代码片段进行编辑,但它仍然没有被接受:/但是我认为代码片段仍然相关,因为它演示了如何page.waitForSelector使用
2021-05-01 13:14:18
waitForXPath() ?
2021-05-08 13:14:18
您不需要代码片段即可转到网页来回答此问题。在搜索waitForSelector@shafeen之前先学习puppeteer,如果它不转到网页,这个问题也被认为是错误的,因为这个平台不是提供免费复制粘贴的代码,而是学习。
2021-05-13 13:14:18

如果要确保元素实际上可见,则必须使用

page.waitForSelector('#myId', {visible: true})

否则,您只是在 DOM 中查找元素,而不是检查可见性。

如果元素的高度/宽度为 0,这将不起作用。请检查此答案以了解stackoverflow.com/a/54103671/528468
2021-04-22 13:14:18
在我的情况下,我需要相反的方法,即page.waitForSelector('#myId', {hidden: true})等到加载程序被隐藏后再继续
2021-04-30 13:14:18

注意,直到今天提交的所有答案都是错误的

因为如果Exist 或 Location Visible 或 Displayed,它会回答一个元素but NOT

正确的答案是使用page.waitFor()检查元素大小或可见性page.waitForFunction(),请参阅下面的说明。

// wait until present on the DOM
// await page.waitForSelector( css_selector );
// wait until "display"-ed
await page.waitForFunction("document.querySelector('.btnNext') && document.querySelector('.btnNext').clientHeight != 0");
// or wait until "visibility" not hidden
await page.waitForFunction("document.querySelector('.btnNext') && document.querySelector('.btnNext').style.visibility != 'hidden'");

const btnNext = await page.$('.btnNext');
await btnNext.click();

解释

存在于页面 DOM 上的元素如果具有 CSS 属性并不总是可见的,display:none或者visibility:hidden为什么使用page.waitForSelector(selector)不是一个好主意,让我们看看下面的片段中的不同之处。

在上面的代码片段中,函数isExist()是模拟

page.waitForSelector('#myId');

我们可以看到,同时运行isExist()两个元素#idA#idB是回报存在。

但是,当运行isVisible()#idA不可见或dislayed。

这里还有其他对象来检查元素是否显示或使用 CSS 属性display

scrollWidth
scrollHeight
offsetTop
offsetWidth
offsetHeight
offsetLeft
clientWidth
clientHeight

用于样式visibility检查与 not hidden

注意:我不擅长 Javascript 或英语,请随时改进此答案。

这对我有用
2021-04-28 13:14:18
@finn,除非下一页具有完全相同的选择器,否则您无法区分当前页面和下一页。waitForFunction允许你这样做。
2021-05-01 13:14:18
绝对正确!然而,在 puppeteer 中实际上有一个选项。看我的回答。
2021-05-13 13:14:18

您可以使用page.waitFor(), page.waitForSelector(), 或page.waitForXPath()来等待页面上的元素

// Selectors

const css_selector = '.btnNext';
const xpath_selector = '//*[contains(concat(" ", normalize-space(@class), " "), " btnNext ")]';

// Wait for CSS Selector

await page.waitFor(css_selector);
await page.waitForSelector(css_selector);

// Wait for XPath Selector

await page.waitFor(xpath_selector);
await page.waitForXPath(xpath_selector);

注:在参照框架,你也可以使用frame.waitFor()frame.waitForSelector()frame.waitForXPath()

等待 page.waitFor 不是多余的吗?
2021-04-17 13:14:18
是的,现在它也被弃用了。
2021-04-21 13:14:18

更新了一些优化的答案:

const puppeteer = require('puppeteer');

(async() => {
    const browser = await puppeteer.launch({headless: true});
    const page = await browser.newPage();

    await page.goto('https://www.somedomain.com', {waitUntil: 'networkidle2'});
    await page.click('input[value=validate]');
    await page.waitForSelector('#myId');
    await page.click('.btnNext');
    console.log('got it');

    browser.close();
})();