こんにちは、おかちゃんせんせいです!
先日Webスクレイピングする方法と、Excel VBAでスクレイピングするための初期設定方法について記事にまとめました。
【業務効率化】Windows版Excel VBAでChromeを自動操作して、Webスクレイピングする方法(初期設定編)初期設定が完了すれば、あとは実装するだけ。
VBAでSeleniumを利用するとき、ある程度決められたメソッドを使い回すことになるので、VBAの知識が少しでもあれば開発していくことができます。
ただ、Webスクレイピングするマクロを開発していくためには、HTMLに関する基礎知識が必要になります。
そこで、今回はExcel VBAでWebスクレイピングするために必要な情報と、実際にWebデータをExcelに転記する方法についてサンプルコードをご紹介します。
目次
欲しいデータを取得するためにはHTML要素を理解する
先述の通り、Webサイトから欲しい情報を取得するためには、最低限HTML要素に関する理解が必要になります。
とはいえ、VBAやHTML初心者の方にとっては、VBAだけではなく、HTMLに関することをイチから覚えるのは結構ハードルが高いと思います。
なので、あくまでコーディングするために最低限必要な情報のみに絞ってお届けます。
キーワードはXPathです。
そもそもXPathとは?
XPathとはXML Path Languageの略称で、ツリー構造となっているXMLやHTMLドキュメントから、特定の要素や属性値などを指定するための言語になります。
XMLやHTMLという単語を一度は耳にしたことはあるかと思いますが、どちらもファイルの書き方のルールの一つです。
今回はWebサイトからデータを取得したいので、HTMLデータを解析していくことになります。
その際に、XPathは簡単に言うと、Webページで表示されている情報について記述してある位置・場所を表したものになります。
例えば、Google Mapを開いて特定の地点を表現するためには、緯度と経度の情報が必要になります。
(例)富士山 緯度:35.39802、経度:138.72766
HTMLの場合には、タグ(html・body・divなど)とタグに囲まれた要素などが必要で、それらによってWebページは表現されます。
なので、欲しい情報の場所を特定こそが、Webスクレイピングをする上で必須になります。
その場所を表現する言語の一つが、XPathです。
XPathはブラウザ上で簡単に取得できる。
XPathについては、ブラウザ上で特に何も機能追加しなくても簡単に取得できます。
ただし、Safariではできないため、ChromeやFirefoxのどちらかを利用します。
今回はChromeを利用するので、ChromeでXPathを取得する方法について簡単に手順を説明します。
③取得したいXPathのところで右クリックする
→検索モードの該当の場所にカーソルを合わせると、Webサイトで表示される場所がハイライトされる
④[Copy] – [Copy XPath]をクリックする
以上のステップで、Chromeの検証モードを利用すれば簡単にトップニュースのXPathを取得できます。
ちなみに、取得したXPathは下記の通りです。
//*[@id=”tabpanelTopics1″]/div/div[1]/ul/li[1]/article/a/div/div/h1/span
このXPathが意味することは
「このページで、id属性が”tabpanelTopics1“の要素の直下にあるdiv要素で囲われたspan要素」
ということです。
Webページを表示するためのHTMLはツリー構造になっている
HTMLはツリー構造で構成されており、tabpanelTopics1(トップニュース)に関する記述は、下図の赤枠部分で表現されています。
Yahoo!ページに限らず、Webページ(HTML)は上図のようなツリー構造になっている、ということをまず理解してください。
取得したXPathの内容をすべて理解するわけではないですが、Webスクレイピングをする上では必須になります。
ちなみにYahoo!ページの左カラムのXpathを調べてみると、下記の通りでした。
//*[@id=”ToolList”]/ul/li[1]/div/a/p/span[1]/span
もし仮に、自動処理の過程で、検索入力欄に入力して『検索』ボタンをクリックしたい場合には、その両方のXPathを取得する必要があります。
//*[@id=”ContentWrapper”]/header/section[1]/div/form/fieldset/span/input
//*[@id=”ContentWrapper”]/header/section[1]/div/form/fieldset/span/button
では、早速Excel VBAでコーディングして、Yahoo!サイトの情報をExcelへ転記する作業を自動化してみましょう。
①Webサイトから欲しい情報のXPathを取得する。
今回はYahoo!サイトのトップニュースに表示されているニュース題名を、すべて取得してみたいと思います。
まずは、トップニュースの一番上から順番に、8記事分のXPathを取得します。
//*[@id=”tabpanelTopics1″]/div/div[1]/ul/li[1]/article/a/div/div/h1/span
//*[@id=”tabpanelTopics1″]/div/div[1]/ul/li[2]/article/a/div/div/h1/span
//*[@id=”tabpanelTopics1″]/div/div[1]/ul/li[3]/article/a/div/div/h1/span
//*[@id=”tabpanelTopics1″]/div/div[1]/ul/li[4]/article/a/div/div/h1/span
//*[@id=”tabpanelTopics1″]/div/div[1]/ul/li[5]/article/a/div/div/h1/span
//*[@id=”tabpanelTopics1″]/div/div[1]/ul/li[6]/article/a/div/div/h1/span
//*[@id=”tabpanelTopics1″]/div/div[1]/ul/li[7]/article/a/div/div/h1/span
//*[@id=”tabpanelTopics1″]/div/div[1]/ul/li[8]/article/a/div/div/h1/span
②SeleniumでWeb上の情報を取得する
次は、Excel VBAで実際に取得したXPathの情報を取得してみましょう。
XPathの情報を取得するためのメソッドは下記の通りです。
driver.FindElementByXPath(“◆◆◆“).XXXX
◆◆◆:XPath
XXXX:Click, Textなどのメソッド
今回は取得したXPathの文字列を取得したいので、XXXXにはTextを使います。
driver.FindElementByXPath(“//*[@id=““tabpanelTopics1””]/div/div[1]/ul/li[1]/article/a/div/div/h1/span”).Text
ここで注意していただきたいのが、◆◆◆の部分です。
Webサイトから取得したXPathに「“◆◆◆”」(ダブルコーテーション)で囲まれた部分がある場合には、さらにその部分をダブルコーテーションで囲む必要があります。
③Excelを開いて、VBEでコーディング&実行する
②まで終われば、あとは実装をしていくだけ。
ExcelのA列2行目から順番に転記。
記述したサンプルコードが下記です。
Sub test()
'変数:driver でSelenium制御
Dim driver As New Selenium.ChromeDriver
'ByクラスはSelenium独自搭載のクラス
Dim myBy As New By
'初期起動時に開くURL
Dim siteURL As String
'Selenium利用時、ウィンドウサイズを最大化で開く初期設定
driver.AddArgument "disable-gpu"
driver.AddArgument "start-maximized"
'SeleniumでChromeを使用する初期設定
Call driver.Start("chrome")
'指定のURLに移動する
siteURL="https://www.yahoo.co.jp"
driver.Get (siteURL)
'Excelに転記する
Range("A2")=driver.FindElementByXPath("//*[@id=““tabpanelTopics1””]/div/div[1]/ul/li[1]/article/a/div/div/h1/span”).Text
Range("A3")=driver.FindElementByXPath("//*[@id=““tabpanelTopics1””]/div/div[1]/ul/li[2]/article/a/div/div/h1/span”).Text
Range("A4")=driver.FindElementByXPath("//*[@id=““tabpanelTopics1””]/div/div[1]/ul/li[3]/article/a/div/div/h1/span”).Text
Range("A5")=driver.FindElementByXPath("//*[@id=““tabpanelTopics1””]/div/div[1]/ul/li[4]/article/a/div/div/h1/span”).Text
Range("A6")=driver.FindElementByXPath("//*[@id=““tabpanelTopics1””]/div/div[1]/ul/li[5]/article/a/div/div/h1/span”).Text
Range("A7")=driver.FindElementByXPath("//*[@id=““tabpanelTopics1””]/div/div[1]/ul/li[6]/article/a/div/div/h1/span”).Text
Range("A8")=driver.FindElementByXPath("//*[@id=““tabpanelTopics1””]/div/div[1]/ul/li[7]/article/a/div/div/h1/span”).Text
Range("A9")=driver.FindElementByXPath("//*[@id=““tabpanelTopics1””]/div/div[1]/ul/li[8]/article/a/div/div/h1/span”).Text
End Sub
サンプルコードをコピペしましたら、実際にマクロを実行してみてください。
下記のようにWebデータがExcelに転記されます。
【改良】繰り返し処理がある場合
上記サンプルコードでも欲しい結果を得ることができます。
ただ、Excelに転記するところのコードがメンテナンスが面倒だと思いませんか?
仮に転記場所を修正したり、取得するXPathに変更があったりすると、全行すべて修正を加えなくてはいけなくなり、余分な作業が増えてしまいます。
こういった見た目同じような処理をしているところは、繰り返し文(For〜Next)で処理できないか考えてみることが、コーディングする上では大切です。
Range("A2")=driver.FindElementByXPath("//*[@id=““tabpanelTopics1””]/div/div[1]/ul/li[1]/article/a/div/div/h1/span”).Text
Range("A3")=driver.FindElementByXPath("//*[@id=““tabpanelTopics1””]/div/div[1]/ul/li[2]/article/a/div/div/h1/span”).Text
Range("A4")=driver.FindElementByXPath("//*[@id=““tabpanelTopics1””]/div/div[1]/ul/li[3]/article/a/div/div/h1/span”).Text
Range("A5")=driver.FindElementByXPath("//*[@id=““tabpanelTopics1””]/div/div[1]/ul/li[4]/article/a/div/div/h1/span”).Text
Range("A6")=driver.FindElementByXPath("//*[@id=““tabpanelTopics1””]/div/div[1]/ul/li[5]/article/a/div/div/h1/span”).Text
Range("A7")=driver.FindElementByXPath("//*[@id=““tabpanelTopics1””]/div/div[1]/ul/li[6]/article/a/div/div/h1/span”).Text
Range("A8")=driver.FindElementByXPath("//*[@id=““tabpanelTopics1””]/div/div[1]/ul/li[7]/article/a/div/div/h1/span”).Text
Range("A9")=driver.FindElementByXPath("//*[@id=““tabpanelTopics1””]/div/div[1]/ul/li[8]/article/a/div/div/h1/span”).Text
改めて該当の部分だけ着目してみると、左辺はA2, A3, A4・・・といった具合に行番号が+1ずつされています。
右辺では、この部分(//*[@id=““tabpanelTopics1””]/div/div[1]/ul/li[1])の li[] に囲まれた数字が1, 2, 3・・・といった具合に+1ずつされています。
両辺とも+1ずつ増えていっていることを見抜けば、あとはFor〜Next文で表現するだけです。
For i = 1 To 8
Range("A" & (i+1)) = driver.FindElementByXPath("//*[@id=““tabpanelTopics1””]/div/div[1]/ul/li[" & i & "]/article/a/div/div/h1/span”).Text
Next i
先ほどと比べて、かなりスッキリ分かりやすくなったと思いませんか?
このように繰り返し同じような処理が行われているところがあれば、VBAでコーディングする際にはFor〜Next文のような繰り返し処理ができないか検討してみることをお勧めします!
Sub test()
'変数:driver でSelenium制御
Dim driver As New Selenium.ChromeDriver
'ByクラスはSelenium独自搭載のクラス
Dim myBy As New By
'初期起動時に開くURL
Dim siteURL As String
'Selenium利用時、ウィンドウサイズを最大化で開く初期設定
driver.AddArgument "disable-gpu"
driver.AddArgument "start-maximized"
'SeleniumでChromeを使用する初期設定
Call driver.Start("chrome")
'指定のURLに移動する
siteURL="https://www.yahoo.co.jp"
driver.Get (siteURL)
'Excelに転記する
For i = 1 To 8
Range("A" & (i+1)) = driver.FindElementByXPath("//*[@id=““tabpanelTopics1””]/div/div[1]/ul/li[" & i & "]/article/a/div/div/h1/span”).Text
Next i
End Sub
次回はWebスクレイピングでよく使うメソッドと、その使い方について特集します。
- WebサイトのデータはXPathで取得する
- XPathはChromeかFirefoxの検証モードで取得できる
- VBAでWeb制御を制御する構文は決まっているため、基本はコピペで対応可能
- 同じようなXPathを連続して取得する際には、繰り返し処理ができないか検討してみる
一つ目は、
侍エンジニア塾
です。
VBAやJavaScript関連でネット検索したことがある方であれば、一度は見かけたことある名前かと思います。
JavaやPython、C言語、VBA、JavaScriptなど、様々なプログラミング言語をオンラインで習得するためのサービスを提供しているところなので、自分が習得したい言語がもしありましたら、無料体験レッスンを受けてみると良いかもしれません。
そこでプロ講師に相談をして、習得するプログラミング言語に対して直接質問するのがベストです。
ストアカ
です。
こちらはあえてプログラミング学習専門ではなく、もっと手軽に学ぶ機会を得るサービスをチョイスしてみました。
VBAやJavaScriptなどのワンツーマンレッスンを開催している講師が多数登録しているので、まずは出費を抑えて学習したいと考えている方にお勧めです。