要素が表示されるまで待機するように操り人形師に指示できるかどうかを知りたいです。
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();
これを達成する方法はありますか?
そのために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();
});
注、上記の答えはすべて間違っています!
ExistまたはLocatedbut NOT
VisibleまたはDisplayed
正しい答えは、 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>
関数isExist()
の上のスニペットでは、simulateです
page.waitForSelector('#myId');
両方の要素#idA
に対してisExist()
を実行しているときに、#idB
が存在することを確認できます。
ただし、isVisible()
を実行すると、#idA
は表示されず、表示されません。
そして、他のオブジェクトは、要素が表示されているか、CSSプロパティdisplay
を使用しているかどうかを確認します。
scrollWidth
scrollHeight
offsetTop
offsetWidth
offsetHeight
offsetLeft
clientWidth
clientHeight
スタイルvisibility
については、hidden
ではなくチェックします。
注:私はJavascriptまたは英語が苦手です。この回答を自由に改善してください。
要素が実際に表示されるようにする場合は、使用する必要があります
page.waitForSelector('#myId', {visible: true})
それ以外の場合は、DOMで要素を探しているだけで、可視性を確認していません。
page.waitFor()
、 page.waitForSelector()
、または page.waitForXPath()
を使用して、 page の要素を待機できます。
// 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 を参照する場合、
frame.waitFor()
、frame.waitForSelector()
、またはframe.waitForXPath()
。
いくつかの最適化で回答を更新しました:
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();
})();