Web ページの情報にアクセスするニーズは昔から存在しましたが、かつては、それは API を駆使する大仕事でした。
その後 WinSock コントロールや WinInet コントロールのような ActiveX が登場し、VB レベルでも何とかなるようにはなりましたが、それでもなお『お手軽』と呼ぶには程遠い状態で有り続けたのです。
状況が変わり始めたのは WebBrowser コントロールが出現した頃からで、フォーム上に Web ページを表示できて HTML ソースにもアクセス可能な WebBrowser コントロールは、今では最も使用頻度の高い ActiveX コントロールの一つになっています。
以下は WebBrowser コントロールを使用して HTML ソースを取得する方法について解説したサイトの一例です。
要は Internet Explorer に出来ることは、ほとんど何でも出来るわけで、この手法で多くのニーズがカバーできます。
ただし、これはあくまでブラウザです。
画面に表示することが前提のコントロールであり、たとえ非表示にしたとしても、ロードしたら IE のレイアウトエンジンが解析を始めます。
当然 Flash や JavaScript や多量の画像が埋め込まれたページをロードすると、完了までにある程度のタイムラグが発生します。
しかし中には HTML ソースさえ取得できれば画像の表示なんて要らない、欲しいのはソース中の特定の一部の情報だけなんだ、という場合も有るでしょう。
実はお手軽さでは決定版とでも呼ぶべき COM コンポーネントが存在します。
XMLHTTP オブジェクトを使えば、それが可能になるのです。
※ 本トピックでは、HTML ソースを手っ取り早くオンメモリで取得する簡単な方法について解説しています。単にファイルとして保存できれば事足りる場合や、より詳細な制御を行いたい場合には、本手法は適していません。その場合は、先に関連情報を参照してください。
XMLHTTP オブジェクトは、その名の通り、Microsoft 社が XML 対応として開発した COM コンポーネントに含まれるオブジェクトです。
主眼が XML だったので、元々は(たぶん)XML 開発者の余計な負担を減らすことが目的で、XML ドキュメントを取得するために必要な HTTP アクセスを極端に簡略化して実装したのでしょうが、それが結果的に XML を超えて逆に汎用的な HTTP ダウンロード ツールの決定版として機能することになります。
とは言え、登場してから約 5 年が経過する 2003 年現在(執筆時点)も、私が見るところではまだ一般に認知されているとは言い難い面があります。
実際には初期のバージョンである MSXML.XMLHTTPRequest(現在は MSXML2.XMLHTTP)が登場したのは IE4.0/Windows 98 の頃で、なんと Access 2000 にも付属していました。(知ってました?^^;)
つまり Win95+IE3.02+Access 97 というような環境でもない限り、ほぼ確実にどこにでも存在するということです。事実上、標準装備と言っても過言では無いでしょう。
これを一部の XML/Web 開発者だけに使わせておくのは、余りにももったいない話です。
御託はこの辺にしておいて、サンプルコードに移りましょう。
これをコピペするだけで、Microsoft 株式会社のサイトのトップページの HTML ソースを取得することが出来ます(事前にネット接続は確認しておいてください ^ ^;)。
汎用コメントが多いので若干長くなっていますが、集約すると正味たった 5 行のコードです。
呆れるほど簡単ですね。
アーリーバインディングを行ないたい場合は、「Microsoft XML, vx」に参照設定をして、下記のように変数宣言します。
ただし、この場合は環境に msxml2.dll か msxml3.dll 以降が存在していることを確認しておいてください。
ではここで、もう少し具体的な例に取り組んでみましょう。
Yahoo!ファイナンスには、右図のようなマーケットサマリーがリアルタイムで表示されています。
この情報を取り出して MS-Access で利用できれば、私のような財界人にとっては大変ありがたい話です。
ちなみにサマリーに表示されているジャスダック指数って何を指しているかご存知ですか。
これは、コミケで同人誌に注ぎ込んだ金額の対ボーナス比をエンゲル係数で割った数値です。(ウソです)
日本の経済状況を推し量るには欠かせない指数ですね。
さて、まずは HTML ソースを取得する汎用関数を用意するとしましょう。
ちょっと変わっているのは、引数 url が URL 文字列か検査している箇所くらいですね。
自力実装が面倒だったので、Office API の FIsHttpUrl 関数を呼んで済ませています。
This information from Mr.Michael Kaplan. Thanks Mike! I owe You lots.
Access 2002 以降の場合は API 宣言を「mso.dll」に変更する必要が有るので、注意してください。
また念のため引数 url の検査方法としてもう二種類、Shell Light-weight Utility API の PathIsURL 関数と URL Monikers API の IsValidURL 関数も用意しています。サンプルコード中では結局使用していませんが、必要であればいつでも FIsHttpUrl 関数から PathIsURL 関数あるいは IsValidURL 関数に切り替えることが出来ます。
後は前出のサンプルコードを組み変えただけですね。
これで HTML ソースを取得することは出来ました。
しかし欲しいのは Yahoo!ファイナンスのコンテンツの中でも、マーケットサマリーだけです。
したがって、HTML ソースからマーケットファイナンスのセクションを取り出して解析する必要が有るわけですが、そのためにはまず、HTML の構成を事前に把握しておかないことには解析のしようもありません。
Yahoo!ファイナンスをブラウザに表示させ、ソースを覗いてみましょう。
これを見ると、「マーケットサマリー」というタイトルの後から表示文字列を 17 個取ればよさそうです。
HTML タグの分離などを考えると、これは正規表現を使ったほうがいいかもしれません。
正規表現は VBScript の RegExp オブジェクトから利用できます。
RegExp オブジェクトを使用するには VBScript のバージョン 5 以上が必要です。
VBScript のバージョン 5 は Microsoft Internet Explorer 5.0 に含まれています。
ゆえに、これから提示するコードは IE 5.0 以降の環境であれば動作します(三段論法?)。
では、コードです。
簡単にコードの説明をしておきましょう。
まず正規表現のパターン文字列として ">[^<>/]+<" を指定します。
これは表示される文字列を取得するためのパターンで、言葉で説明すると「 ">" で始まり、"<"、">"、"/" のいずれでもない 1 文字以上の文字を含み、"<" で終わる文字列を取得せよ」という意味になります。
ご存知のように HTML タグは "<" で始まり ">" で終わります。
したがって、その逆を検索しているわけです。
ただしパターンの先頭と末尾に ">" と "<" を含んでしまうため、出力時に Mid$ 関数で切り出しを行なっています。
パターンに一致した文字列は MatchCollection コレクションに格納されるので、これをループでチェックしていって、"マーケットサマリー" という言葉を含んでいたら、その次のループから 17 回単語を出力して終了させています。
もし実行環境に VBScript のバージョン 5.5(Microsoft Internet Explorer 5.5 以上に含まれています)が存在することを保証できるのであれば、Mid$ 関数による切り出しは SubMatches オブジェクトを使うことによって不要になるでしょう。
以下は上記コードの一部を SubMatches オブジェクトを使って書き直したものです。
変更箇所(2 箇所)は太字で示しています。
' 表示文字列のみのコレクションを取得します。 re.Pattern = ">([^<>/]+)<" re.Global = True ' 全体を対象とします。 Set mc = re.Execute(str) ' サマリー開始位置を取得します。 For i = 0 To mc.Count - 1 If InStr(mc(i), TITLE) Then j = i + ITEM_COUNT ' 出力上限添字をセットします。 Exit For End If Next ' サマリーのみを出力します。 For i = i + 1 To j Debug.Print mc(i).SubMatches(0) Next
パターン文字列内で括弧で括った箇所は、後で SubMatches コレクション(の先頭要素)として参照することが出来ます。
これにより、Mid$ 関数による切り出しを簡略化することが出来ます。
正規表現と RegExp の詳細については、市販の書籍あるいは下記リンクを当たってください。
ちなみに実行結果は以下の通りです。
| イミディエイト |
この辺のロジックは人それぞれだと思います。
結果さえ正しく取得できれば、特にロジックは問いません。
XMLHTTP オブジェクトには、今回取り上げた用途以外にも、たとえば画像データのようなバイナリファイルをダウンロードしたり、逆に ASP へ送信(POST)したりといった使い方が有ります。
詳細は MSDN や Web スクリプト関連のリソースでご確認ください。
なお、私は XML にも HTTP にも正規表現にも特に詳しいわけでは有りません。
誤認・誤謬については、ご指摘いただければ幸いです。
本サイト内の関連情報については、下記トピックを参照してください。
WinHTTP ライブラリで Web スクレイピング(1)〜 GET 編〜
WinHTTP ライブラリで Web スクレイピング(2)〜 POST 編〜
なお本トピックおよび上記トピックは、いずれも Web ページをオンメモリにロードする方法です。
メモリ上で操作/処理を行なう必要が無く、単にローカルファイルとして保存したいだけの場合は、URLMON API の URLDownloadToFile 関数を使用できます。
URLDownloadToFile 関数の Microsoft 社による使用例については、下記を参照してください。
また URLDownloadToFile 関数を VBA から使用する例として、おそらく最良の解説は、下記で参照することができます。
URLDownloadToFile APIを使用してダウンロードしてみた
ローカル キャッシュが取得されてしまう場合は、DeleteUrlCacheEntry 関数で事前にキャッシュを削除することで、最新の HTML ソースを取得することが出来ます。
さらに高度な HTTP アクセスを行いたい場合は、下記を参照してください。
miyabi's Homepage - Technic - HTTPやFTPを使用してファイルのダウンロードする方法。
Happy! Happy! Island - Access VBA Tips+α - 番外編1.HTTPやFTPを使うには
上記により、大容量のファイルを転送する際にプログレスバーを表示するなどの対応が可能になります。
XMLHTTP を利用した VBA による株価データの取得と分析のより本格的な例をお探しの方は、下記を参照してください。
Excel を使用した例ですが、ほとんどのサンプルが Access にも応用可能です。