名前指定でウインドウ(タブ)を切替える事ができる
スクレイピング中にリンクをクリックすると別のURLが表示されます。
同じウインドウの中でURLの情報だけが切り替わればそのままスクレイピング続行となります。
しかし別のURLを展開する際は必ず別ウインドウで起動するという仕様になっている事もあります。
よって操作側では通常はウインドウの開閉をコントロールするのは難しいです。
(参考:Ctrl+リンクをクリックすると必ず別ウインドウに指定のURLを展開する事ができます)
- クリックなどのイベントによって表示されたウインドウにある要素を使いたい
- 隠れてしまったウインドウにある要素も使いたい
このようにどのウインドウでスクレイピングを継続するのかはその時の流れによります。
ケースによって制御対象のウインドウをつかめるようにしておきたいものです。
Seleniumではウインドウのタイトルを指定する事で欲しいウインドウを掴むことができます
比較的簡単なコードです。すぐ使えるコードですので是非使ってみてください。
この本で勉強しました
Seleniumbasic(セレニウムベーシック)について最初に勉強した本です。
Seleniumの本はよくあるのですがSeleniumbasicについて解説されている本は非常に少ないです。
Seleniumbasicに関する記事は20ページほどしか無いですが十分勉強になります。
一般的に売られている本とは見た目も内容も一線を画すものになっていますよ。
電子書籍はこちらになります。
関連記事
後程紹介するコードではリンクをクリックするというコードを使っています。
クリックだけでも色々な種類があります。右クリックも再現可能です。
ウインドウの切り替えと合わせて使う【selenium×VBA】右クリックを含めたマウス操作を再現
ウインドウを切り替えた後で画面の最大化を行うとよりスクレイピングでエラーが出にくくなります。
複数のウインドウから1つのウインドウを選択(定義)する理由
「各URLの要素はウインドウに紐付いているから」です。
Selenium側から見るとウインドウが複数展開されているとどのウインドウから情報を取得するのか分かりません。
ウインドウが1つの時は定義しなくて良いです。定義しなくてもウインドウが指定出来ているからです。
しかしウインドウが2つ以上画面に居る時はどちらのウインドウに対して操作をするのか指示が必要です。
具体例
ウインドウAでスクレイピング中にリンクをクリックした際別ウインドウが立ち上がったとしましょう。
立ち上がったウインドウをBとします。ウインドウBは最前面に配置されたとします。
この時ウインドウBはアクティブになっていますがあくまで「最前面に配置されているだけ」です。
この状態では依然としてWebドライバーはウインドウAを選択しています。
ウインドウBでスクレイピングを継続するにはWebドライバーに指示を出す必要があります。
操作対象を特定する必要がある
アクティブ状態のウインドウ=操作対象のウインドウではないという事です。
よって作業対象のウインドウを切り替えたい時は都度指示が必要です。
コードを含めた作業内容を紹介
先に作業内容を紹介します。その後コード、コードの解説と続きます。
作業内容
私のブログの記事一覧からある記事のリンクをクリックします。
その後記事内のh2タグのテキストをイミディエイトウィンドウに出力するという作業になります。
リンク先URLのタイトル画像のすぐ下にある文字です。(画像下部赤枠参照)
アウトプット
コード実行後のVBEです。
イミディエイトウィンドウには文字が入っています。(画像下部赤枠参照)
コード全体
今回使用したコードです。オレンジ色のボタンを押すことでコードがコピーされます。
ご自身のVBEに貼ってから以降の解説をご覧ください。
Sub windowを選択する()
'変数の定義
Dim Driver As New ChromeDriver 'ドライバーはChromeを選択
With Driver
'1_ブラウザを起動後指定のURLにアクセス
.Start "chrome"
.Get "https://www.slt-pgming-21.net/2022-02-21-123000/"
.Window.Maximize
.Wait 1000
'2_画面スクロール
.ExecuteScript "return document.querySelector('#toc4')." _
& "scrollIntoView ({behavior:'smooth' ,block:'start' })"
.Wait 2000
'3_指定の記事のリンクをクリック
.FindElementByXPath("/html/body/div[1]/div[3]/div/main/" _
& "article/div/ul[2]/li[8]/a").Click
.Wait 1000
'4_新規ウインドウをつかむ
.SwitchToWindowByTitle _
("【VBA×selenium×JS】任意の要素まで簡単にスクロール | EnjoyExcel")
.Wait 1000
'5_h2タグの情報をイミディエイトウィンドウに書き出す
Debug.Print .FindElementByXPath _
("/html/body/div[1]/div[3]/div/main/article/div/h2[1]/span").Text
End With
End Sub
構成
やっている事は5つです。
- 1ブラウザを起動後指定のURLにアクセス
- 2画面スクロール
- 3指定の記事のリンクをクリック
- 4新規ウインドウをつかむ
- 5h2タグの情報をイミディエイトウィンドウに書き出す
解説
コードの構成に沿って解説します。
1_ブラウザを起動後指定のURLにアクセス
Chromeドライバーを選択して指定のURLにアクセスします。Getメソッドを使っています。
詳細知りたい方はこちらの記事を参照ください。
参考VBA×Selenium×ChromeでWebスクレイピング|nameタグを使う
2_画面スクロール
Javascriptを使っています。詳細知りたい方はこちらの記事を参照ください。
参考【VBA×selenium×JS】任意の要素まで簡単にスクロール
3_指定の記事のリンクをクリック
1つ前で紹介した画面スクロールの記事へのリンクをクリックしています。
FindElementByXPathメソッドを使っています。詳細知りたい方はこちらの記事を参照ください。
参考VBA×Chrome/Edgeでスクレイピング|XPathとは?|動画で解説
4_新規ウインドウをつかむ
Chromeドライバークラス内のSwitchToWindowByTitleメソッドを使います。
リンク先URLの記事タイトルを引数に指定しましょう。
引数はStringですのでダブルクォーテーションで挟む事を忘れない様にしてください。
ウインドウオブジェクト(クラス)を戻り値として返してきます。
引数Titleはタブ内全ての文字を指定しましょう。変数や&(アンパサンド)も使えます。
引数として用意するタイトルは省略できません。省略するとエラーが出ます。
タイトルを取得する方法
タイトルが長くタブに映り切らない時はタイトルを取得し確認しましょう。コードはこちらです。
String型の変数 = ChromeDriver.Window.Title
別のプロシージャを用意しリンク先にアクセスして上のコードを使ってタイトルを取得しましょう。
取得したタイトルはコピーしてそのままSwitchToWindowByTitleメソッドの引数に使えます。
5_h2タグの情報をイミディエイトウィンドウに書き出す
ここもXPathを使っています。
4番のコードが無いとウインドウフォーカスが切り替わりません。
よってコードの10行目で最初にアクセスしたURLの情報を取得してしまいます。
4番のコードでウインドウを切り替えた結果リンク先のURLの情報が取得できている事を確認しましょう。
補足情報
4番の解説で使った画像の中に2つのメソッドが映っています。
- SwitchToNextWindowメソッド
- SwitchToPreviousWindowメソッド
SwitchToNextWindowメソッドで追加されたウインドウにフォーカスが移ります。(右のタブ)
SwitchToPreviousWindowメソッドで1つ前のウインドウにフォーカスが移ります。(左のタブ)
引数無しで使えるメソッドです。非常に使いやすいです。
SwitchToWindowByTitleメソッドを使わなくてもこれらのメソッドだけでも十分戦力になります。
まとめ
これでスクレイピングしたいウィンドウを自分のタイミングでつかめるようになりました。
スクレイピングをする前まではアクティブな画面にフォーカスが向いていると決めつけていました。
今までどのウィンドウにフォーカスが向いているのかなんて考えた事も無かったです。
Excelシートは基本的にシートを指定しなければアクティブになっているシートに命令が入ります。
よってWebブラウザのウインドウも同じかと思っていましたが甘かったです。
VBAでもオブジェクト変数を使ってシートやブックを変数に格納しますね。
同じようにウィンドウを指定して使えばアクティブじゃなくても情報が取得できる事が分かりました。
オブジェクト変数について知りたい方は以下記事をご覧ください。
オブジェクト変数とは?VBAで転記|ブック間で文字列をコピペするマクロの作り方を教えます