こんにちは、blueです。
前回はHTMLのタグ構造について説明しました。
前回の記事はこちら
タグ構造を理解できればHTMLコードからの要素の取得は容易にできそうです。
しかし、大量のHTMLコードの中から1つの要素を取得するにはもう一つの内容を理解する必要があります。
- (スクレイピングに必要な)HTMLのタグ構造
- (スクレイピングに必要な)HTMLのツリー構造
そこで今回はHTMLのツリー構造に関しての説明をします。
また実際にスクレイピングする際のコードについても説明します。
ここまで理解できればHTMLから要素を取得することもできるようになります。
今回もできる限りわかりやすく説明しますので是非読んでいってください。
なお今回の書籍は以下を参考にしました。
HTMLとCSSを基礎から学びたいという方はこちらの書籍がお勧めです。章ごとの最初にポイントがまとめられていたり、対話形式で理解する部分もあったりで理解しやすいように工夫されています。
HTMLとCSSの知識と技術をしっかりと学びたいという方はこちらの書籍がお勧めです。デザインと書かれているだけあってページ内の区分けが綺麗ですし、図やコードもカラフルなので視覚的にもわかりやすい書籍になっています。
HTMLのツリー構造
次のようなページを考えてみます(あくまで理解用なので実際のルールは無視しています)。
上のページのHTMLは以下になります。
<body>
<div>
<h1>ページタイトル</h1>
<p>見出し文</p>
</div>
<div>
<h1>ページタイトル</h1>
<p>見出し文</p>
<p>見出し文</p>
<p>見出し文</p>
</div>
</body>
コードは<body><div><h1>~</h1></div></body>とタグの中にタグが入った形になっています。
これを「入れ子構造」といいます。
HTML文書全体はhtml要素を最上位とする入れ子で成り立っています。
これをHTMLのツリー構造と呼びます。
階層構造をわかりやすく示したのが以下になります。
ここで上位のものを親要素、下位のものを子要素といい、さらに下は孫要素、同列のものを兄弟要素と呼んだりします。
ここで重要なのは「それぞれの要素には親や子が存在する」ということです。
スクレイピングでは親を意識することが必要になってきます。
同一タグから単一要素を取得する
ここからは実際のスクレイピングについて説明をします。
以下のような構造において一番下のテーブルを取る場合を考えます。
HTMLは以下になります。
<body>
<div id="data1">
<table>~~</table>
</div>
<div id="data2">
<table>~~</table>
</div>
<div id="data3">
<table>~~</table>
</div>
<div id="data4">
<table>~~</table>
</div>
</body>
この場合の取得は2つの方法があります。
FindElements〇〇〇(Index)で指定する
FindElementsByTagは複数の同一タグを持つ要素をすべて取得するメソッドです。
Driver直下に置くことでhtml文書内で条件にあてはまるものをすべて取得します。
また引数にインデックス番号を指定することで単一の要素を取ることができます。
4つ目の<table>の要素の内容をイミディエイトウィンドウに出力するコードは以下になります。
Dim Driver As New Selenium.WebDriver
Debub.Pring Driver.FindElementsByTag("table")(4)
ただこの場合はtableタグの個数を1つずつ数える必要があるのとtableタグの個数が変わったときは再度設定する必要があり少し面倒です。
FindElement〇〇〇で指定する
この方法は親の要素である<div id=”data4″>の要素を取得したのちに子要素を取得するというものです。
SeleniumのFindElementByは重ねて記載することができます。
4つ目の<table>の要素の内容をイミディエイトウィンドウに出力するコードは以下になります。
Dim Driver As New Selenium.WebDriver
Debub.Pring Driver.FindElementsById("data4").FindElementByTag("table")
この方法を使えば親要素で範囲を狭めた後に子要素を特定するようなことが可能になります。
この場合は親要素によって範囲が特定される為、以降のFindElementByTag(“table”)に該当するものが一つとなり単一要素を取得できます。
なおFindElementByTagなどで指定する場合、要素が2つ以上ある場合は1つ目しか取れません。
できる限り親の要素で固定してあげるとよいです。
同一タグから各々の要素を取得する
次は以下のような構造において各々の<p>を取る場合を考えます。
HTMLは以下のようになります。
<body>
<div id="data1">
<p>~~</p>
<p>~~</p>
<p>~~</p>
<p>~~</p>
</div>
<div id="data2">
<p>~~</p>
<p>~~</p>
<p>~~</p>
<p>~~</p>
</div>
</body>
この場合の取得はFor~Nextを使用した以下の方法があります。
For i=1 To n ~Next
これはFindElementsByTagで取得する<p>の個数を数えておいて一つずつ処理する方法です。
各々の<p>の要素の内容をイミディエイトウィンドウに出力するコードは以下になります。
Dim Driver As New Selenium.WebDriver
For i=1To 4
Debug.Print Driver.FindElementById("data1").FindElementsByTag("p")(i).Text
Next i
この方法で各要素を取得することは可能ですがあらかじめ個数を数える必要があります。
For Each elm in elms ~Next
FindElementsメソッドは要素に適合するすべての要素を検索、取得します。
このコレクションに対してはFor Eachでループを書くことが可能であり、この操作を行うことですべての要素に対して1つずつ処理することができます。
各々の<p>の要素の内容をイミディエイトウィンドウに出力するコードは以下になります。
Dim Driver As New Selenium.WebDriver
Dim elms As WebElements
Dim elm As WebElement
Set elms = Driver.FindElementById("data1").FindElementsByTag("p")
For Each elm In elms
Debug.Print elm.Text
Next i
この方法だと個数をカウントする必要もなく、すべての同一タグについて同じ処理を行うことができます。
なお上記の処理は使い分けになります。
上位10位までの情報を取りたい場合はi=1 To 10のように書けばいいですし、すべての要素を取りたい場合は For Each で回すことになります。
行いたい処理によって使い分ければよいと思います。
今回のまとめ
今回は
・(スクレイピングに必要な)HTMLのツリー構造
について説明をしました。
また実際にスクレイピングする際のコードについても説明しました。
HTMLに関してはここまで理解していればかなりの処理はできるようになると思います。
あくまでスクレイピングをする為の最低限の情報ですが参考になれば幸いです。
今回の書籍は以下を参考にしました。
HTMLとCSSを基礎から学びたいという方はこちらの書籍がお勧めです。章ごとの最初にポイントがまとめられていたり、対話形式で理解する部分もあったりで理解しやすいように工夫されています。
HTMLとCSSの知識と技術をしっかりと学びたいという方はこちらの書籍がお勧めです。デザインと書かれているだけあってページ内の区分けが綺麗ですし、図やコードもカラフルなので視覚的にもわかりやすい書籍になっています。
↓困ったときは以下が頼りになります。私も利用させてもらってます😊。
Selenium-VBAでのWebスクレイピングに関する記事はこちらをどうぞ
【ExcelVBA‐Selenium】【永久保存版】スクレイピングに必要なSeleniumのインストール方法教えます
【Selenium-VBA】Yahooメールへのログイン方法をわかりやすく説明する
ChromeでのWebスレイピングをできる限りわかりやすく説明する(Excel VBA)
【ExcelVBA‐Selenium】Chrome driverのバージョンエラーが出た時の対処法(2021/10/7更新)
【Selenium-VBA】Seleniumを用いたスクレイピングでテーブル情報を取得する1
【Selenium-VBA】スクレイピングをするのに必要なHTMLについて説明します1
【Selenim-VBA】起動済みのChromeを用いてSeleniumによるスクレイピングを行う
【Selenium-VBA】JavaScriptを使ってスクレイピングをしてみる1
【VBA】SeleniumBasicにおけるクラス、メソッド、プロパティ一覧(日本語版)
Web-APIを用いたデータ取得に関する記事はこちらをどうぞ
【VBA】Web APIを使ってデータを取得する(OpenWeatherMap)1
【VBA】Web APIを使って時間別天気予報を取得する(気象庁API)
【VBA】Web APIを使ってLINE通知を行う(LINE Notify)1
コメント