3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Puppeteer で button を click しても効かないときに試したこと

Posted at

現場でWebスクレイピングする機会がありました。
pupteer を使っていくなかで詰まったことがあったので、もし同じ状況で詰まっている人がいれば、参考になるかもしれません。

今回click()メソッドが期待する動作をしなかったので、その時の状況と解決策を書いていきます。

開発環境

  • Windows10 version: 21H2
  • Node.js version: v16.14.1
  • Puppeteer version: 5.5.0

原因

  • セレクタが間違っている
  • ブラウザを開いているが、--window-sizeに問題がありクリックするボタンが表示されていない
  • クリックする要素が表示される前にclick()が実行されてしまっている
  • なぜかclick()が使えない ※後述します。

おそらくクリックが効かない原因のほとんどは、該当すると思います。
期待する動作にならないなら、まずはこのあたりをしっかり確認すると解決するかもしれません。

セレクタが間違っている

まず最初に確認してみましょう。
ここが間違っていると、どんなに他の原因を探っても解決しません。

クリックに限りませんが、Webスクレイピングでうまく要素を取得できない場合は、だいたいセレクタに問題があると思います。
console.logなどを仕込んで、ちゃんとボタンを指定できているか確認しましょう。

ブラウザを開いているが、--window-sizeに問題がありクリックするボタンが表示されていない

今回私が詰まった原因です。
ほとんどのサイトがレスポンシブ対応しているので、Puppeteer で開いているブラウザのサイズはしっかり確認しておきましょう。

Puppeteer では、ブラウザの設定を下記の方法で設定できます。
headless: falseは、ブラウザをヘッドレスモードで実行するかどうかを設定します。

デフォルトではtrueとなっているので、ブラウザが開けているか、要素をクリックできているか、ページ遷移の状況などを確認するために、開発時にはfalseと設定するとよいでしょう。

(例) item.js
 const browser = await puppeteer.launch({
   headless: false,
   ignoreHTTPSErrors: true,
   args: [`--window-size=1920,1080`],
   defaultViewport: {
     width: 1920,
     height: 1080
   }
 });

その他のオプションの設定は、ドキュメントを参考に設定してみてください。
Puppeteer

クリックする要素が表示される前にclick()が実行されてしまっている

Puppeteer には、多くのwaitForメソッドがあります。

waitForSelector()waitForTimeout()を使って、クリックしたい要素が出現するまで、プログラムの実行を止めましょう。
期待する値がとれない場合や、期待する動作をしない場合はwaitForが不足している可能性もあります。

なぜかclick()が使えない

調べたところ、Puppeteer で開いたブラウザに、要素が表示されていない場合、エラーになることがあるようです。
つまり、click()メソッドは、開いたブラウザに、要素(ここではボタン)が表示されるまでスクロールなどをしないといけないようです。

例えば、ページネーションのボタンをクリックしたいとき、多くのサイトがページ下部に設置されていると思います。
そのため Puppeteer でブラウザを開いただけだと、ページネーションのボタンが表示されていないと判定され、「クリックする要素が見つからない」というエラーが出るのだと思います。
(私の環境だと発生しました)

ではどうすればいいのか?

私は下記の方法を使って解決しました。

(例) item.js
// ページが表示されるまで待つ
await page.waitForSelector(ITEM_PAGE_QUERY);
// ボタン要素を取得する
const nextPageButton = await page.$(NEXT_PAGE_QUERY);
await nextPageButton .evaluate(b => b.click());

evaluate()メソッドを使用する方法です。
stackoverflow の下記の質問がよくまとまっているので、参考にするとよいでしょう。
Puppeteer in NodeJS reports 'Error: Node is either not visible or not an HTMLElement'

まとめ

  • セレクタが間違っていないか確認する
  • 開いているブラウザサイズに問題がないか確認する
  • クリックする要素が表示される前に実行していないか確認する
  • evaluate(b => b.click());を使ってみる

Puppeteer クリックで詰まっている人の参考になると嬉しいです!
また、間違っている情報などありましたら、ご指摘いただけると幸いです。

3
1
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
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?