よく「ExcelVBAでIE操作!」と謳ってるサイトはたくさん見るけど、「○○のやり方」っていう特定の機能ごとの記事ばかりで、通して何かを作ってる所は見たことが無い気がする。ということで、実際に動くツールを作る企画をやってみようと思います。
はじめに
VBAに限ったことではありませんが、プログラミング習得後に「さぁ何か作ろう!」と思っても、そもそもどんな物をつくれるのかが分からない。覚えた処理をどうやって組み合わせればいいのかも分からない。結局手を出せずにそのまま放置してしまった。
そんな経験はありませんか?
書籍や学習サイトで計算や判定などの「処理の仕方」は覚えても、一つのツールとして「組み上げる力」は実際に作ってみないと身に付きません。
今回は実際に制作物を作りつつ、どんな時にどんな処理を使っていけば良いのかを順序立てて説明していきたいと思います。
※少々長くなりますので、3本立ての予定です。
目標成果物
クラウドワークスやランサーズといったクラウドソーシングサイトで制作依頼の多い、「ウェブスクレイピングツール」を作ります。
今回は「食べログ」のページから、東京にある飲食店の1ページ目にあるお店の情報をエクセルに取得するツールを作ってみたいと思います。サイトに負荷を与えない様、お店の詳細ページには入らないものとします。
【対象物】ウェブスクレイピングツール
【操作対象ページ】食べログ-東京都飲食店(https://tabelog.com/tokyo/)
【取得データ】店舗名、料理種別、検索キーワード
VBAでウェブページを起動する
まずはExcelを起動し、VBエディターを開きましょう。
適当な標準モジュールを一つ作成し、関数とそこで扱うInternetExplorer(以下IE)変数を一つずつ作成します。
「objIE」という変数を宣言してAsからの後ろの型指定を入力する際、いつもなら型予測の候補が出てくるのに、「InternetExplorer」の場合は出てこないと思いませんでしたか?
実はこのままではIEの操作を行うことはできないため、「参照設定」を行いIEを扱う準備をしなければいけません。
タブ上の「ツール」から「参照設定」を開いて下さい。
この様なウィンドウが表示されますので、下記二つの項目を探し出しでチェックを入れて下さい。
・Microsoft HTML Object Library
・Microsoft Internet Controls
チェックを入れた後は「OK」を押してウィンドウを閉じ、正しく設定されているかどうかもう一度「参照設定」を開いて確認しておきましょう。
上記の様になっていれば問題ありません。※環境によってチェックの入っている項目の数が異なる場合がありますが、「Microsoft HTML Object Library」、「Microsoft Internet Controls」の二つにチェックが入っていれば問題ありません。
それでは先ほどのDim宣言の下に以下のコードを入力した後、実行して見て下さい。
Set objIE = CreateObject(“InternetExplorer.Application”) objIE.Visible = True |
IEが起動し、真っ白な画面が表示されていれば成功です。そのIEの画面は使用しませんので閉じて構いません。
2行目の「Visible = True」の処理は忘れずに行う様にしましょう。この処理を記述しないまま実行を繰り返すと見えないIEウィンドウが裏で大量に作られてしまい、PCが重くなる原因となってしまいます。
また、今後「既に起動中のIEを操作する」という処理を行う際に、うまく動かない原因となる可能性があります。
タスクマネージャーなどから終了させることもできますが、慣れていない内は上記2行の処理は必ずセットで記述する様にして下さい。
一気に量が増えましたが、次は以下の赤色の部分のコードを追加してみましょう。
Option Explicit
Const READYSTATE_COMPLETE = 4 Sub main() |
「objIE.Navigate2」で指定したURLのページに移動することができます。
次のDoループでは、「IEのページが読込を完了するまで待つ」という処理を行っています。「objIE.BusyがTrue、またはobjIE.readyStateがREADYSTATE_COMPLETE(4)以外の場合にループを継続する」となっています。
「.Busy」を呼び出すと、IEがデータの読み込み中かどうかを確認することができます。「True」が返ってきた場合は読み込み中、「False」の場合は読み込み中では無いということになります。
「.readyState」はIEの状態を指します。返ってくる値は以下の5種類があります。
戻り値 | 説明 |
---|---|
0 | デフォルト値。未完了状態。 |
1 | IEオブジェクトのロード中状態。 |
2 | IEオブジェクトのロード完了状態。ただし操作不可能状態。 |
3 | IEオブジェクトの操作可能状態。 |
4 | IEオブジェクトの全データ読み込み完了状態。 |
基本的に「4」以外を使用することは無いので、4だけ覚えておきましょう。
「readyState」の値で読み込みが完了したかどうかが判断できるのなら、「Busy」を見る必要は無いんじゃないの?と考えるかと思いますが、この戻り値も完璧という訳では無いので読み込み完了の状態でも何らかのデータをダウンロードしている場合があり、Busyを見るとTrueが返ってくる。というケースが存在します。
念のため、両方の値を判定しておきましょう。
最後にMsgboxを使って読み込みが完了したページのタイトルを表示させています。上記のコードでは問題無くページのタイトルが表示されると思います。
ではここで試しに、ページ読み込み確認の処理をコメントアウトした状態で実行しするとどうなるかを確認してみます。
Option Explicit
Const READYSTATE_COMPLETE = 4 Sub main() Dim objIE As InternetExplorer |
上記のコードを実行すると、大体の場合以下の様なエラーが発生します。
※環境によってエラーの表示内容は異なる可能性があります。
「デバッグ」を押してエラーの箇所を確認してみると、「Msgbox」の行で発生していることが分かると思います。「objIE.document.Title」と記述することでそのページのタイトルが取得できるのですが、ページ読み込みがまだ完了していないため『「document.Title」というデータにアクセスができない』ということでエラーとなります。
恐らく、Do~Loopの読み込み処理をコメントアウトしていないのにエラーが発生した!という方も居ると思います。その場合何度か繰り返し実行してみて下さい。エラーが出る時と出ない時がありませんか?
はい、実はこれではまだ完全に読み込み判定ができない場合があるのですが、それはまた別の機会に書いていきたいと思います。
次からはページ内の要素にアクセスしてみましょう。