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();
Есть ли способ сделать это?
Ответы
Ответ 1
Я думаю, вы можете использовать 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();
});
Ответ 2
Вы можете использовать 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()
.
Ответ 3
Обновленный ответ с некоторыми оптимизациями:
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();
})();
Ответ 4
Обратите внимание, все вышеприведенные ответы неверны!
Потому что он отвечает за элемент, если он существует или находится, 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)
не является хорошей идеей, давайте рассмотрим разницу во фрагменте ниже.
function isExist(selector) {
let el = document.querySelector(selector);
let exist = el.length != 0 ? 'Exist!' : 'Not Exist!';
console.log(selector + ' is ' + exist)
}
function isVisible(selector) {
let el = document.querySelector(selector).clientHeight;
let visible = el != 0 ? 'Visible, ' + el : 'Not Visible, ' + el;
console.log(selector + ' is ' + visible + 'px')
}
isExist('#idA');
isVisible('#idA');
console.log('=============================')
isExist('#idB')
isVisible('#idB')
.bd {border: solid 2px blue;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="bd">
<div id="idA" style="display:none">#idA, hidden element</div>
</div>
<br>
<div class="bd">
<div id="idB">#idB, visible element</div>
</div>