入れ子になっているHTMLの要素を取得するVBAコードについて

スポンサーリンク

サイトの作り方によっては固有の要素を特定できないことがある

これまでVBAでIEを操作する方法について、いくつかご紹介してきました。

私自身も多くのページの自動処理、情報取得などのツールを作ってきましたが、中には要素の抽出に苦戦するものもありました。

今回は要素を特定しにくいサイトで、望んだ部分の要素の値を抽出するのに役立つ入れ子になったデータを抜き出す方法についてご紹介します。

要素を特定する際にId属性以外は複数ある場合が多い

IEで表示されるページの中でからある場所の値を抜き出したり、特定のテキストボックスに値を入力する場合、その要素を取得する必要があります。

要素を取得するためには、要素に割り振られているIdやName、CalssName、TagNameなどの属性を指定する必要があり、この部分がIE操作の最も大事な部分です。

ただし要素の属性情報は重複しているものが多く、重複がないのはId属性のみです。
他の属性で要素を特定する場合、インデックス番号を特定する必要があり、そのインデックス番号が可変の場合などは特に特定がしにくくなります。

今回はこの重複のある属性情報の中から目的としている要素を取り出す方法の1つとして「入れ子になっている要素を取得する方法」をご紹介します。

スポンサーリンク

表(テーブルタグ)からの情報取得について

今回私がご紹介する具体的なコードはHTMLで作成された表(テーブルタグ)の中から特定の行の値を抜き出すというものです。

テーブルタグはTable、Tr、Th、Tdなどのクラス名(ClassName)が指定されていますが、Id属性やName属性が割り振られていることはほぼなく、取得したい部分をピンポイントで値を抜き出すのが難しいです。

大手のECサイトなどでは表にテーブルタグを使うことは少ないようですが(SEOの関係ですかね?)、私が仕事で使うサイトはまだまだテーブルタグを使っているものが多かったです。

よって有名なサイトを操作する目的では今回私が紹介するコードをそのまま使用する機会は少ないですが、仕事で使っている会社のシステムなどではかなりテーブルタグを使っているものが多い気がしますし、入れ子の要素を取得する方法はテーブルタグ以外でも応用できるので便利なコードだと思います。

表の特定の部分のみ抽出する方法

今回私が作成したVBAコードはこちらのページの医薬品の比較表から価格を抜き出すというものです。
(私の作成した別のサイトを一例に用いています。)

Declare PtrSafe Sub Sleep Lib “kernel32” (ByVal dwMilliseconds As Long)

Sub ページ開いて表の中から値を取得する()

Dim IE As Object
Set IE = CreateObject(“InternetExplorer.Application”)
’IEのページの位置を指定する(TopとLeftはなくても良い)
IE.Top = 0
IE.Left = 0
IE.Visible = True

Sleep 1000

’目的のページに遷移
IE.navigate (“http://otcdrugs-healthfoods.info/alinaminnoruijihin/”)

’ページ読み込みの待機
Do While IE.Busy Or IE.readyState < READYSTATE_COMPLETE
DoEvents
Sleep 1
Loop
Sleep 3000

Dim Table
Dim TableRow
Dim TableCell
Dim i, x, y, z

’全てのテーブルを取得
Set Table = IE.document.getElementsByTagName(“Table”)
’すべてのテーブルの中から「商品パッケージ」と「15歳以上」の言葉を含む表を抜き出し特定する
For i = 0 To Table.Length - 1
If InStr(Table(i).innerText, “商品パッケージ”) > 0 And InStr(Table(i).innerText, “15歳以上”) > 0 Then
x = i
Exit For
End If
Next

’特定した表のすべての行の中から「価格」と「円」の言葉を含む行を抜き出し特定する
Set TableRow = Table(x).getElementsByTagName(“Tr”)
For i = 0 To TableRow.Length - 1
If InStr(TableRow(i).innerText, “価格”) > 0 And InStr(TableRow(i).innerText, “円”) > 0 Then
y = i
Exit For
End If
Next

’特定した行のセルの値をワークシートのセルに記載する
Set TableCell = TableRow(y).getElementsByTagName(“TD”)
For i = 0 To TableCell.Length - 1
Cells(1, i + 1) = TableCell(i).innerText
Next

Set TableCell = Nothing
Set TableRow = Nothing
Set Table = Nothing

IE.Quit ’IEのページを閉じる場合
Set IE = Nothing

End Sub

今回のVBAコードのポイント

今回ご紹介したコードのポイントは下記2点です。

①要素の取得方法と目的の要素を取り出す方法

document.getElementsByTagNameやdocument.getElementsByName、document.getElementsByClassNameはインデックス番号を指定せず取得した場合、すべての要素を配列のような形で取得できます。(厳密には配列とは異なるようですが)

インデックス番号の最小は0、最大値はLengthプロパティで指定(.Length – 1)できるため、すべてのインデックス番号について繰り返して値を調べることで目的のものを特定して取得することが可能になります。

②document.getElementsByTagNameなど要素を指定するメソッドは入れ子にできる

テーブルの中の行の情報を取得するにはTrタグ自体のインデックス番号を指定しても良いのですが、ページ内にどれだけのTrタグが存在するのか確認するのは困難です。

そういった際にテーブルを先に指定し、その中のTrタグを取得する方法として入れ子で取得するのが有効です。

  • Set Table = IE.document.getElementsByTagName(“Table”)
  • Set TableRow = Table(x).getElementsByTagName(“Tr”)
  • 別々に変数に格納しなくても下記のように一気に入れ子にしても問題ありません。
    (インデックス番号を取得しないといけないので使う機会は少ないかもしれませんが)

  • Set TableRow = IE.document.getElementsByTagName(“Table”)(x).getElementsByTagName(“Tr”)
  • さらにその中のTdタグを取得する際にはさらに入れ子の構造で取得すれば大丈夫です。

    おすすめ書籍 (広告)

    コメント