LoginSignup
5
5

More than 5 years have passed since last update.

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

Last updated at Posted at 2018-03-01

早速注意なのですが、現状暫定対応で凌いでおり個人的にしっくりしておりません。
なので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:存在しない要素

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

5
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5