web-dev-qa-db-ja.com

操り人形師:要素が見えるのを待つ?

要素が表示されるまで待機するように操り人形師に指示できるかどうかを知りたいです。

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();

これを達成する方法はありますか?

23
Vivien Pipo

そのために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();
});
27
turmuka

注、上記の答えはすべて間違っています!

ExistまたはLocatedbut NOTVisibleまたは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または英語が苦手です。この回答を自由に改善してください。

17
ewwink

要素が実際に表示されるようにする場合は、使用する必要があります

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

それ以外の場合は、DOMで要素を探しているだけで、可視性を確認していません。

12
finn

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()

7
Grant Miller

いくつかの最適化で回答を更新しました:

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();
})();
3
luschn