Puppeteerを新規インストールしてGoogle検索すると大概失敗、稀に成功します。
公式サンプルのGoogle Developers検索は動くのにGoogle検索は何でしっかり動かんの?となりました。
原因はGoogle検索画面のデザインでした。
事象
puppeteerを新規にnpmインストール。
C:\src\js\puppeteer-smpl>npm install puppeteer
> puppeteer@1.18.1 install C:\src\js\puppeteer-smpl\node_modules\puppeteer
> node install.js
Downloading Chromium r672088 - 141 Mb [====================] 100% 0.0s
Chromium downloaded to C:\src\js\puppeteer-smpl\node_modules\puppeteer\.local-chromium\win64-672088
npm notice created a lockfile as package-lock.json. You should commit this file.
+ puppeteer@1.18.1
added 43 packages from 22 contributors and audited 50 packages in 29.133s
found 0 vulnerabilities
動作確認の為にGoogle検索する以下のコードを実行すると「Google 検索」ボタンを押す行でエラーが発生。
const puppeteer = require("puppeteer");
(async () => {
const browser = await puppeteer.launch({
headless: false,
defaultViewport: { width: 1024, height: 1024 }
});
const page = await browser.newPage();
await page.goto("https://www.google.co.jp/");
await page.type('input[title="検索"]', "ほげ");
await page.click('input[value^="Google"]');
await page.waitForNavigation();
const title = await page.title();
console.log(title);
await browser.close();
})();
発生したエラー。
C:\src\js\puppeteer-smpl>node index.js
(node:23092) UnhandledPromiseRejectionWarning: Error: Node is either not visible or not an HTMLElement
at ElementHandle._clickablePoint (C:\src\js\puppeteer-smpl\node_modules\puppeteer\lib\JSHandle.js:199:13)
at process._tickCallback (internal/process/next_tick.js:68:7)
-- ASYNC --
at ElementHandle.<anonymous> (C:\src\js\puppeteer-smpl\node_modules\puppeteer\lib\helper.js:111:15)
at DOMWorld.click (C:\src\js\puppeteer-smpl\node_modules\puppeteer\lib\DOMWorld.js:367:18)
at process._tickCallback (internal/process/next_tick.js:68:7)
-- ASYNC --
at Frame.<anonymous> (C:\src\js\puppeteer-smpl\node_modules\puppeteer\lib\helper.js:111:15)
at Page.click (C:\src\js\puppeteer-smpl\node_modules\puppeteer\lib\Page.js:986:29)
at C:\src\js\puppeteer-smpl\index.js:12:16
at process._tickCallback (internal/process/next_tick.js:68:7)
(node:23092) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:23092) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
原因
検索窓に文字を打つと「Google 検索」ボタンがページ本体から候補ウィンドウへ移動する。
この間隙を縫ってpuppeteerがアクセスしてしまい、エレメントが見つからない状態になる。
この為まれに検索ボタンが押せるが大抵のケースで失敗する。
対処
検索窓にキーワードを打つ際、delayを入れてあげることで候補ウィンドウに「Google 検索」ボタンエレメントが移動するのを待ってば良い。
await page.type('input[title="検索"]', "ほげ", { delay: 100 });
その他の対処法
ボタン押下をevaluateで囲む。
https://github.com/GoogleChrome/puppeteer/issues/2977
// await page.click('input[value^="Google"]');
await page.evaluate(() => {
document.querySelector('input[value^="Google"]').click();
});