Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

puppeteerでどのwaitForが失敗しているか分からず詰まった話

More than 1 year has passed since last update.

早速注意なのですが、現状暫定対応で凌いでおり個人的にしっくりしておりません。
なのでcoolな解決法がございましたら教えてください。

2018/06/13 追記
今は解消されていると思います!

暫定対応(飛ばしたい人はこちらから)

さて、困っていることはタイトルの通りだが、うだうだ文章に書くより実際にコードを載せたほうが早いと思うので下記が該当のものになる。

sample.js
const puppeteer = require('puppeteer');

(async () => {
    const browser = await puppeteer.launch({
        args: [
            '--no-sandbox',
            '--disable-setuid-sandbox',
        ]
    });
    process.on('unhandledRejection', (reason, p) => {
        console.log(reason, p);
        browser.close();
    });
    const page = await browser.newPage();
    await page.goto('https://www.google.com/');
    await page.type("#lst-ib", "puppeteer");
    await page.click('input[name="btnK"]');
    await page.waitFor('#rso > div > div > div:nth-child(1) > div > div.rc > h3 > a');
    await page.waitFor('存在しない要素', {timeout: 1});
    browser.close();
})();

で、上記を実行したときのコンソールがこちら

$ node sample01
Error: waiting failed: timeout 1ms exceeded
    at Timeout.WaitTask._timeoutTimer.setTimeout (/home/operational_work/puppeteer/node_modules/puppeteer/lib/FrameManager.js:695:58)
    at ontimeout (timers.js:475:11)
    at tryOnTimeout (timers.js:310:5)
    at Timer.listOnTimeout (timers.js:270:5) Promise {
  <rejected> Error: waiting failed: timeout 1ms exceeded
    at Timeout.WaitTask._timeoutTimer.setTimeout (/home/operational_work/puppeteer/node_modules/puppeteer/lib/FrameManager.js:695:58)
    at ontimeout (timers.js:475:11)
    at tryOnTimeout (timers.js:310:5)
    at Timer.listOnTimeout (timers.js:270:5) }

エラーログとしてはtimeoutで落ちているのかはわかったのだが、どのwaitForで落ちているのかはわからないのでそれを解決したい。

試したこと

assert入れればいいんじゃない?

早速トライ

sample.js
const puppeteer = require('puppeteer');
const assert = require('assert');

(async () => {
    const browser = await puppeteer.launch({
        args: [
            '--no-sandbox',
            '--disable-setuid-sandbox',
        ]
    });
    process.on('unhandledRejection', (reason, p) => {
        console.log(reason, p);
        browser.close();
    });
    const page = await browser.newPage();
    await page.goto('https://www.google.com/');
    await page.type("#lst-ib", "puppeteer");
    await page.click('input[name="btnK"]');
    await page.waitFor('#rso > div > div > div:nth-child(1) > div > div.rc > h3 > a');
    assert(await page.waitFor('存在しない要素', {timeout: 1}));
    browser.close();
})();

コンソール

$ node sample01
Error: waiting failed: timeout 1ms exceeded
    at Timeout.WaitTask._timeoutTimer.setTimeout (/home/operational_work/puppeteer/node_modules/puppeteer/lib/FrameManager.js:695:58)
    at ontimeout (timers.js:475:11)
    at tryOnTimeout (timers.js:310:5)
    at Timer.listOnTimeout (timers.js:270:5) Promise {
  <rejected> Error: waiting failed: timeout 1ms exceeded
    at Timeout.WaitTask._timeoutTimer.setTimeout (/home/operational_work/puppeteer/node_modules/puppeteer/lib/FrameManager.js:695:58)
    at ontimeout (timers.js:475:11)
    at tryOnTimeout (timers.js:310:5)
    at Timer.listOnTimeout (timers.js:270:5) }

ダメだ変わらん…

バックトレース仕込めばいいんじゃない?

sample.js
const puppeteer = require('puppeteer');

(async () => {
    const browser = await puppeteer.launch({
        args: [
            '--no-sandbox',
            '--disable-setuid-sandbox',
        ]
    });
    process.on('unhandledRejection', (reason, p) => {
        console.trace();
        browser.close();
    });
    const page = await browser.newPage();
    await page.goto('https://www.google.com/');
    await page.type("#lst-ib", "puppeteer");
    await page.click('input[name="btnK"]');
    await page.waitFor('#rso > div > div > div:nth-child(1) > div > div.rc > h3 > a');
    await page.waitFor('存在しない要素', {timeout: 1});
    browser.close();
})();

コンソール

$ node sample01
Trace
    at process.on (/home/operational_work/puppeteer/sample01.js:12:17)
    at emitTwo (events.js:126:13)
    at process.emit (events.js:214:7)
    at emitPendingUnhandledRejections (internal/process/promises.js:94:22)
    at runMicrotasksCallback (internal/process/next_tick.js:124:9)
    at _combinedTickCallback (internal/process/next_tick.js:131:7)
    at process._tickCallback (internal/process/next_tick.js:180:9)

あ、そうなるのね……。

暫定対応

色々ググってみたがようわからんとなり、どうしたか言うと……。

sample.js
const puppeteer = require('puppeteer');

(async () => {
    const browser = await puppeteer.launch({
        args: [
            '--no-sandbox',
            '--disable-setuid-sandbox',
        ]
    });
    process.on('unhandledRejection', (reason, p) => {
        console.log('失敗したwaitFor:' + selector);
        browser.close();
    });
    const page = await browser.newPage();
    let selector;
    const waitFor = x => {
        selector = x;
        return page.waitFor(selector, {timeout: 500});
    };
    await page.goto('https://www.google.com/');
    await page.type("#lst-ib", "puppeteer");
    await page.click('input[name="btnK"]');
    await waitFor('#rso > div > div > div:nth-child(1) > div > div.rc > h3 > a');
    await waitFor('存在しない要素');
    browser.close();
})();

waitForのラッピング関数を作って、selectorをどんどん上書いて失敗したのをログに出した。

で、コンソール

$ node sample01
失敗したwaitFor:存在しない要素

一応、目的は達成したけどなんか腑に落ちにない……。
なので、アドバイス等を募集中です。

ri-zhi
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away