パスを指定したうえで属性を取得する事ができる
Webスクレイピングに慣れてくるとWebアプリケーション(以下WebApp)を操作できる様になります。
そうなると「日常業務もSeleniumで自動化させることができるのでは?」と考える様になります。
- WebAppへの入力作業
- WebAppにクエリを与えて情報を取り出す
実際の業務では社内で使用するWebAppを操作し情報を作成、抽出する事になります。
端的にWebAppを操作すると書いてますが仕様、方法は様々です。
システムによっては複雑な操作も必要になる事が想定されますね。
そんな中あるWebAppを操作する際以下のような事が出来ないかずっと考えていました。
指定したパスに特定のClassが存在するのかを確認しClassの有無でその後の仕事を決めたい
キーワードはAttributeメソッドです。具体例は記事の中で紹介します。
指定されたパスから任意の属性値(子要素)を取得する事ができます。
なかなか参考になる情報が無かったのですが継続して調査した結果答えを見つけました。
私と同じことで悩んでいる人がいるかもしれないので記事にします。
この記事を読むとSelenium×VBAでWebアプリケーションを扱う際できる事の幅が広がりますよ。
記事の最後に動画も用意しています。すぐにご覧になりたい方はこちら。
この本で勉強しました
表紙で「ちょっと大丈夫か・・・」と思ってしまうのですが非常に良く出来ている本です。
Selenium関連の書籍は少ないながらも書店やオンラインストアで見かける事はあります。
しかしSeleniumbasic(セレニウムベーシック)について解説されている本は非常に少ないです。
この本は貴重な存在です。読むとVBAの環境の中でWebスクレイピングが学べますよ。
Seleniumbasicに関する記事は20ページほどしか無いですが十分勉強になります。
一般的に売られている本とは見た目も内容も一線を画すものになっていますよ。
電子書籍はこちらです。
関連記事
特定の情報までのパスを取得する方法についてはこちらの記事をご覧ください。
この方法を使えば欲しい情報(テキスト等)を比較的簡単に取得できるようになります。
以降の記事はFindElementByXPathメソッドが理解出来ている前提で話を進めていきます。
ボタンでも属性の確認は付いて回ります。ラジオボタンを使って解説します。
選択状態をチェックする為にボタンの属性を確認しています。
ラジオボタンの取扱説明書Selenium×ExcelVBA|ラジオボタンの選択状態をチェックする方法
結論
FindElementByXPathメソッドの戻り値の要素はWebElementです。
WebElementクラスの中にあるAttributeメソッドを使用します。
これでFindElementByXPathメソッドにて取得したWebElementからClass等の属性を取得できます。
Attributeメソッド
早速コードを書いてみます。ChromeDiverを使ったコードになります。
ChromeドライバークラスのFindElementByXPathメソッドでWebElementを特定します。
続いてWebElementクラスのAttributeメソッドで指定したパスが持っているClassを全部取り出します。
Classが複数ある場合は半角スペースを1つ挟んで連続してクラス名が抽出されます。
実務では使いやすい様に加工してその後の作業につなげることになります。
今回はSplit関数と配列を使って複数のClass名を切り分けて格納しています。
詳細はこの後で出てくるコードをご覧ください。
コードの応用
私はパスを指定したうえで属性(Class)を取得しましたが他にもいろんな事ができます。
特定の属性を指定したうえで他の属性値(要素)を取得する事が出来ます。
○○を指定したうえで△△を取得することができます
○○、△△共に属性が入ります。
○○に入る属性は以下の様に個が特定できるものが多いです。
コードとして用意すると以下のような使い方になります。
FindElementById("○○").Attribute("△△")
FindElementByName("○○").Attribute("△△")
FindElementByXPath("○○").Attribute("△△")
△△には〇〇で指定した要素から取り出したい属性を記入します。
私は今回Classを使っていますが他の要素でも良いです。
具体例は用意していませんが使い方だけ見ると以下の様に使う事も出来ます。
- Idを指定したうえでClassを取得
- Nameを指定したうえでXPathを取得
- XPathを指定したうえでIdを取得
組み合わせで色々な事が出来るようになります。
ご自身の対面しているURLに合わせて情報を取得してみてください。
ハイパーリンクを作る為のURLを取得する
Attributeメソッドではhref属性も取得できます。
取り出したURLを使ってExcelシートにハイパーリンクを作る事も可能です。
事例紹介
画像をご覧ください。
WebAppに直接文字を入力するという仕事を自動化する予定です。
特定のClassを持った行を探して隣の列の値を加工するという作業をします。
- エクセルの様に縦横でシート状の文字を入力するスペースがある
- 作業対象は数百行(画像では省略)×2列(画像にある列1と列2)
- 列1にはプラスボタン(展開用のボタン)がある
- プラスボタンがある場所には *expander* というClassが設定されている
- 列1にプラスボタンが無い時だけ列2の情報を加工したい
課題はAttributeメソッドに解決してもらう
XPathが分かれば行や列をループさせる事は簡単です。
よって全ての情報にアクセスするのは問題無く対応できます。
問題なのはパスを指定したうえでその地点にある情報が保持しているクラスを確認する事です。
行をループする中で都度列1に+ボタンが居るのか確認する必要があります。
この仕事をAttributeメソッドに担当してもらうという建付けです。
Split関数と配列を組み合わせて使います
最終的にClassを取得するのですがClassは1つとは限りません。
よってClassを扱う為にSplit関数を使って情報を加工します。
Split関数は他にも使い道がある汎用性の高い関数ですので是非覚えてください。
Split関数は配列と非常に相性が良いので一緒に使ってみる事にします。
コード
AttributeメソッドとSplit関数を使ったコードです。
Sub 属性を取得する()
Dim r As Long 'For~Nextステートメントで使う数値を入れる為の変数
Dim kws As String 'keywords Classが複数格納される可能性があるので複数形のsをつけた
Dim ary_kw As Variant 'keywordsを個々に格納する為の配列
Dim nbr As Long 'For~Nextステートメントで使う数値を入れる為の変数
Dim Driver As New ChromeDriver
Driver.Start "chrome"
Driver.Get "実際のURL"
For r = 1 To 500 '仮で1~500にしています
'Attributeメソッドを使ったコードです
'変数rを実際のXPathの中に埋め込んで行を周回します
kws = Driver.FindElementByXPath("列1のXPath").Attribute("class")
'変数kwsには複数のClassが入っているのでSplit関数で属性を切って配列に格納
ary_kw = Split(kws, " ")
'配列を周回
For nbr = LBound(ary_kw) To UBound(ary_kw)
'配列内の情報と *expander* というキーワードを照合する
If ary_kw(nbr) Like "*expander*" Then
GoTo n
End If
Next nbr
'ここに列2の値を加工する為のコードを書きます
n:
Next r
End Sub
解説
まずは構成を説明します。
- 1変数の宣言
必要な変数を用意し宣言します
- 2URL接続
GetメソッドでURLを指定して接続します
- 3リスト全体を周回する
For~Nextステートメントを使用しています
仮で1~500という値を使っています
- 4列1に対してプラスボタンの有無を確認
Attributeメソッドを使用しています
- 5取り出したClassを切り分けて配列に格納する
Split関数と配列を使用しています
- 6Classが特定のキーワードと一致するのかを確認
For~Next、Ifステートメントと比較演算子(Like)を使用しています
ループを抜ける為にGoToステートメントを使用しています
- 7列2にある情報を加工する
ここは省略しています
この記事を読んでいるかたは初心者様ではないはずです。細かい説明は省略します。
ここでのポイントはAttributeメソッドと配列とSplit関数、GoToステートメントです。
Attributeメソッドは冒頭で説明しました。
配列は別の記事で解説しています。
Split関数とGoToステートメントだけもう少し具体的に解説します。
Split関数
基本的な関数の構造はこちらです。
番号 | 引数 | 説明 |
---|---|---|
1 | 文字列 | 対象となる文字列を指定します |
2 | 区切文字 | どの文字を使って文字列を区切るのかを指定します |
引き数は文字列のみ必須となります。
区切文字を省略すると半角スペースが区切文字に採用されます。
実際の引数は4つあります。2つはこのコードでは使わないので省略しました。
興味ある方は各自で調べてみてください。
配列と合わせて使うと効率UP
今回は18行目のコードでSplit関数が使われています。
変数kwsは複数のClass名が格納されています。
半角スペースを区切文字としてClass名を切り分け配列に格納しています。
Variant型の変数で受けると配列(先頭番号ゼロから)で格納されます。
この使い方が一番楽で使いやすいです。
GoToステートメント
簡単に言うとコードをショートカットする事ができます。前述のコードを使って説明します。
コードの23行目にある条件分岐でTrueの時は24行目のコードに落ちます。
その際に実行されるコードを用意しましょう。
GoTo の後に目印となる文字を書きます。今回はnと書いています。
しばらくコードが進むと30行目にn:という文字が出てきます。
この組み合わせで24行目に落ちたコードは毎回30行目までコードを飛ばす事が出来ます。
これでClassに*expander*が無かった時の処理を飛ばして次の行に進むようにしています。
多用するのは良くないのですが今回はこんな機能もあるよという事で使ってみました。
動画を用意してみました
文字だけだと分かりにくいところもありますので動画も用意してみました。
応用編
Attribureメソッドなど便利な機能をたくさん組み合わせるとこんなことができます。
「Yahooのニューストピックスをハイパーリンク付きでExcelのワークシート上に取得」なんて事も可能です。
試しにやってみました。記事には動画も用意されています。
まとめ
Attributeメソッドを使える様になったおかげで私の課題もクリアする事ができました。
プラスボタンがある行はスルーしプラスボタンが無い行の値だけ加工する事ができました。
WebスクレイピングができるようになってくるとWebAppの操作が楽しくなってきます。
加えてオブジェクト変数に対する理解が進みます。仕事の幅が広がります。
AttributeメソッドはIsElementPresentメソッドを織り交ぜて使うとさらに深い作業ができるようになります。
ニューストピックスの様に都度要素の文字が変化するようなURLにもスクレイピングが可能になります。