松山事務所のくろもんです。
前回のスクレイピングからしばらくたち、別のサイトのスクレイピングをしようとした際に引っかかったことを残しました。
今回引っかかった内容
前回の内容で、
– 画面をクリックする
– 値を入力する
– 値を取得する
– スクリーンショットを保存する
といったことを行いましたが、実はこれらのコードをよく見ると、関数の実行元となっているpage
オブジェクトは最初に取得してから変更されていないことがわかります。
このpage
オブジェクト、実際にブラウザを表示しながら実行すればよくわかるのですが、ほぼブラウザ上のタブを指しているようなものなのです。
つまり、別画面でページが開く ものや 入力用の子画面が表示されるサイトについては、新たに表示された画面(内容を見たいElementが存在するタブ)を取得しなおす必要があるのです。
試行錯誤の結果
この問題に引っかかった当初は、”タブが新しく作成されるイベントを捕まえて――”とか色々なことを考えましたが、結論だけ言うと、以下の関数を使うだけでどうにかできました。
1 2 3 4 5 6 |
let pages = browser.pages(); for (let page of pages) { if (await page.$(selector).then(res => !!res)) { return page; } } |
browser
オブジェクトはpuppeteerが管理しているブラウザを表すものですが、browser.pages()
を実行すると、このブラウザに存在するタブを、どのウインドウに存在するかに関わらず、全て取得することができます。これを使えば、”現在表示されているタブのうち、特定の要素が存在するタブ”を取得することができるわけです。
タブの特定さえできてしまえば、後は前回と同じやり方で操作することができます。
今回を踏まえて
puppeteerは確かに便利なのですが、ちょっと複雑なことをやろうとすると、やり方がわからず、調べるのに時間がかかってしまうことがあります。
“複雑なことをやる”前に、”もっと単純なやり方で実現できないか”を考えるべきだったのかなと思います。