みなさん、こんにちは!
タカハシ(@ntakahashi0505)です。
エクセルVBAでIEスクレイピングをするときに便利なクラスの作り方をお伝えしております。
前回の記事はこちら。
name属性で要素を探してその内容を取り出すプロパティの作り方をお伝えしました。
今回は、リンクテキストでa要素を探してそのURLのページを開く方法です。
便利そうじゃないですか?
ということで、エクセルVBAでIEを操作するクラスにリンクテキストでa要素を探してリンクする方法です。
では、行ってみましょう!
前回のおさらい
まず、前回のおさらいからです。
まずIEを操作するクラスIEObjectです。
Public IE As InternetExplorer
Public Document As HTMLDocument
Private Sub Class_Initialize()
Set IE = New InternetExplorer
IE.Visible = True
End Sub
Private Sub Class_Terminate()
IE.Quit
End Sub
Public Sub Navigate(ByVal url As String)
IE.Navigate url
Wait
Set Document = IE.Document
End Sub
Public Sub Wait()
Do While IE.Busy = True Or IE.readyState < READYSTATE_COMPLETE
DoEvents
Loop
End Sub
Public Property Get ContentByName(ByVal nameAttr As String) As String
ContentByName = Document.getElementsByName(nameAttr)(0).Content
End Property
だいぶ多機能になってきました。前回はContentByNameプロパティを作りました。
それを検証するための標準モジュールのプロシージャがこちらです。
Sub MySub()
Dim ieObj As IEObject: Set ieObj = New IEObject
ieObj.Navigate "https://tonari-it.com"
Debug.Print ieObj.ContentByName("description")
Debug.Print ieObj.ContentByName("keywords")
End Sub
特定のリンクテキストを持つa要素を取得するメソッド
今回は、ページ内で特定のリンクテキストを持つa要素を探すして、それにリンクするという処理を実現していきたいと思います。
例として、以下のリンクを目指します。
「詳細・お申込みはこちら」というやつですね。みんなに踏んで欲しいやつです。
それで、IEObjectクラスに以下のようなFunctionプロシージャを追加しました。
Public Function GetElementByLinkText(ByVal text As String) As HTMLAnchorElement
Set GetElementByLinkText = Nothing
Dim anchor As HTMLAnchorElement
For Each anchor In Document.Links
If anchor.innerText = text Then
Set GetElementByLinkText = anchor
Exit Function
End If
Next anchor
End Function
Functionプロシージャなのでメソッドになりますね。GetElementByLinkTextメソッドです。
目的はリンクなので、そこまでの処理を含めても良いのですが、汎用性を考えてa要素を返すメソッドにしました。
リンクは標準モジュールから既に実装済みのNavigateメソッドを呼び出します。
Linksプロパティで取得したa要素コレクションをループ
まず6行目ですが、HTMLDocumentオブジェクトのLinksプロパティで、a要素をコレクションで取得しています。
getElementsByTagNameメソッドでa要素を指定しても良いのですが、こっちのほうが短い。
あとは、取得したa要素のコレクションについてループをして、パラメータで与えた文字列にヒットすれば、それを戻り値としてセットしてあげればOKですね。
「含む」にしたい場合は、条件式をInStr関数使うなり、Like演算子使うなりしてあげればOKです。
なぜプロパティではなくメソッドなのか
なぜプロパティにせずにメソッドにしたかというと…けっこう微妙なのですが、このプロシージャの戻り値が「Nothing」であることも多そうなので、メソッドにしました。
なんか、プロパティにしてNothingが多いのって、個人的には違和感が…。あと、既存のgetElement~シリーズもメソッドですし。このへんは結構好みもあると思いますが。
特定のリンクテキストを持つa要素を取得しリンクする
では、標準モジュールでテスト用のプロシージャを作って確認してみましょう。
Sub MySub()
Dim ieObj As IEObject: Set ieObj = New IEObject
ieObj.Navigate "https://tonari-it.com"
Dim text As String: text = "詳細・お申込はこちら"
Dim anchor As HTMLAnchorElement
Set anchor = ieObj.GetElementByLinkText(text)
If Not anchor Is Nothing Then
ieObj.Navigate anchor.href
Else
Debug.Print text; "をテキストとするa要素はありませんでした"
End If
Stop
End Sub
9行目で先ほどのメソッドを呼び出しています。
それで、11行目からIf文の分岐がありますが、目的のリンクテキストのa要素が見つからなかった場合の処理ですね。
存在しているときだけNavigateメソッドでページを開くようにしています。
実行すると、以下のようにページが開きますね。
ちなみに、今回作ったメソッドは、最初に一致するリンクテキストを見つけたら、そのa要素を返します。
目的のリンクテキストがページ内に複数ある場合には想定しない動きをする可能性がありますので、注意くださいね。
まとめ
以上、エクセルVBAでIEを操作するクラスにリンクテキストでa要素を探してリンクする方法をお伝えしました。
このメソッド、実はPythonのseleniumモジュールで標準であったので、「いいな~」と思っていたものでした。
VBAの場合、ひと手間いりますが、自作しておけば使い回しできますので、ぜひ…!
次回はテーブルにトライしたいです。
どうぞお楽しみに!
連載目次:エクセルVBAでIEを操作するクラスを作る
エクセルVBAでInternetExplorerを操作してWebスクレイピング、まだまだ現役で必要となる現場もあるでしょう。このシリーズでは、IEを使ったスクレイピングをするときに便利なクラスの作り方をお伝えします。- エクセルVBAでIEを操作するもっとも簡単なクラスを作成する方法
- エクセルVBAでIEを操作するクラスでWebページを開くメソッドを追加する
- エクセルVBAでIEを操作するクラスに読み込み待ちとドキュメント取得の機能を追加する方法
- エクセルVBAでIEを操作するクラスにname属性で取得した要素から内容を取り出すプロパティを作成
- エクセルVBAでIEを操作するクラスにリンクテキストでa要素を探してリンクする方法
- エクセルVBAでIEを操作するクラスにテーブルのデータを取得するメソッドを追加する方法
- エクセルVBAでIEを操作するクラスにWebページのテーブルデータをシートに書き出すメソッドを追加する
- エクセルVBAでIEを操作するクラスに検索入力&ボタンクリックのメソッドを追加する方法
- エクセルVBAでIEを操作するクラスにログイン処理をするメソッドを追加する方法
- エクセルVBAによるIEを操作するクラスに指定秒数の待ち時間を入れるメソッドを追加する