【エクセルVBAでIE操作】WEBページのテーブル要素を自動で取得する方法


新幹線

photo credit: Shinkansen via photopin (license)

みなさん、こんにちは!
JR東日本さんにはかなりお世話になっています、タカハシ(@ntakahashi0505)です。

初心者向けエクセルVBAでIEを操作するシリーズです。今回はだいぶ本格的なWEBスクレイピングをしていきますよ。

前回はこちらの記事で

【エクセルVBAでIE操作】hタグなどの要素をタグ名でGetする
エクセルVBAでIEを操作する初心者向けのシリーズの6回目です。今回はタグ名で要素をゴソっと取得するgetElementsByTagNameの使い方です。様々なHTML要素を簡単に取得できます。

getElementsByTagNameを使って、特定のHTML要素をタグ名で取得する方法についてお伝えしました。

今回はこれをさらに応用してWEB上の「表」つまり、テーブル要素を取得していきたいと思います。

なにせ、WEBスクレイピングで欲しいのはデータの場合が圧倒的に多いですよね?そしてそのデータは「表」つまりテーブル要素にまとまっている場合が多いわけです。

その方法を知ってしまえば、WEBスクレイピングはかなり制覇したといっても良いのでは?!

ということで早速いってみましょう!

前回のおさらい

前回のプログラムはこちらです。

開いたページのヘッダー要素h1~h3をそれぞれ取得してイミディエイトウィンドウに表示するという内容でした。

getElementsByTagNameでタグ名(h1~h3)を指定することで、該当のHTML要素をコレクションとして取得することができます。

今回はgetElementsByTagNameを使用してテーブル要素をガッツリつかんでいきたいと思います。

HTMLのテーブル要素の仕組み

今回はまたJR東日本さんのページにお手伝い頂きます。このページです。

新幹線の運行情報

JR東日本管轄の新幹線の運行状況のお知らせページですが、運行状況はテーブルで表現されています。

新幹線の運行状況のテーブル

現在は全て平常運転ですね。

なんで、東海道新幹線がないんだ!?って思われるかも知れませんが、お察しください。JR東日本の新幹線はこの5本なのです。

さて、この表がHTMLではどのように表現されているかを見てみましょう。Google ChromeでHTMLソースを見る場合は ctrl + u でしたね。

新幹線運行状況のHTMLソース

HTMLでの表はテーブルタグ<table>~<table>内に記載をします。

このページにはtableタグは1セットのみなのですが、そのtableタグ内はけっこう色々な要素が含まれていてわりとボリュームがありますね。

よく見ますと

新幹線運行状況のtr要素

このように、同じような構造のtrという要素が5つ分で成り立っているようです。

1つ目のtr要素の中には、thという要素があって「東北新幹線」、tdという要素の中にさらにimg要素があってそのalt属性に「平常運転」、あと「&nbsp;」が挟まっているtdという要素がもう一つ。

2つ目以降もその構造は全く同じですね。

実際に表に照らし合わせると

新幹線運行状況のテーブル構造

とこのようになっています。つまりテーブル要素は「table>tr>thまたはtd」という入れ子の構造でできあがっているということになります。

それぞれのタグの役割をまとめますと

  • table:一つの票を定義する。このタグ内行数分のtr要素を記述。
  • tr:表の横一行を定義する。このタグ内に列数分のthやtd要素を記述。Table Rowの略。
  • th:表の見出しセルを定義する。このタグ内に見出しのテキストなどを記述。Table Headerの略。
  • td:表の値セルを定義する。このタグ内にテキストや数字などを記述。Table Dataの略。

です。WEBスクレイピングする場合はこれらのタグの役割をよーく理解する必要がありますので、バシっと覚えてしまいましょう。

getElementsByTagNameを使ってテーブル内のデータを取得する

これでテーブルの構造は把握できましたので、エクセルVBAでそれぞれの要素を取得していきましょう。

この表は新幹線名、運行状況、詳細という3つの列で成り立っています。

ですから、5つあるtr要素それぞれについて

  • 新幹線名:th要素のテキスト
  • 運行状況:1つ目のtd要素の中のimg要素のalt属性
  • 詳細:2つ目のtd要素のテキスト

を取得すればよいということになります。

For Each~Nextで取得したtr要素全てについて繰り返す

プログラムの流れとしては、このページ全体のHTMLドキュメントからtrタグをコレクションとして取得して、そのコレクション内のtr要素一つ一つについて繰り返す、という流れになりますから

というFor Each~Nextの繰り返し処理になります。

th要素をコレクションとして取得しその中のテキストを取り出す

tr要素それぞれについて、各要素を取り出していきます。

まず新幹線名ですが、thタグの中にあります。

手順としては

  1. tr要素の中からth要素をコレクションとして取得
  2. その1番目のth要素(といっても要素数は1つしかありませんが)からテキストを取り出す

という手順になります。

thコレクションを格納するオブジェクト変数をcolTHとします。要素内のテキストを取得するにはinnerTextを使いますから

とすればOKです。コレクション内の要素には登場順に0から採番されますから、colTH(0)はコレクションcolTHの1番目の要素という意味でしたね。

これで新幹線名はGet完了です。

td要素をコレクションとして取得してimgタグのalt属性を取り出す

次が少し難しそうですね。

先ほどの例を参考にすると手順としては

  1. tr要素の中からtd要素をコレクションとして取得
  2. その1番目の要素からimg要素をコレクションとして取得
  3. 取得したimg要素からalt属性を取得

としても良いのですが、実は

  1. tr要素の中からimg要素をコレクションとして取得
  2. その1番目のimg要素(といっても要素数は1つしかありませんが)からalt属性を取り出す

というように、わざわざtdをつかまなくてもその下のimgを直接取りに行っちゃってもOKです。

imgコレクションを格納するオブジェクト変数をcolImgとします。要素内の属性を取得するにはそのまま属性名altで取り出せますから

とします。これで運行状況も取得できました。

td要素をコレクションとして取得してその2番目の要素のテキストを取り出す

運行状況が正常ですと詳細が全く表示されないのでつまらないと言えばつまらないのですが、平和で何よりです。

何も表示はされていないのですがHTMLソース内には「&nbsp」と記載されています。これは何かと言いますと「半角スペース」なのですが、実はいわゆる普通の半角スペースとは異なる特別な半角スペースなんですって。

今回に限ってはそんなにプログラムに影響があるわけではないので、特に気にせずに進めますね。

で、この詳細情報の取得に関しては、これまでの例に倣えば簡単ですね。

手順としては

  1. tr要素の中からtd要素をコレクションとして取得
  2. その2番目のtd要素からテキストを取り出す

という手順になります。

tdコレクションを格納するオブジェクト変数をcolTDとしますと

とすればOKですね。コレクション要素は0から採番されますから、2番目の要素が欲しいときはcolTD(1)で取得できます。

新幹線の運行状況をイミディエイトウィンドウに出力

以上をまとめますと、こんなプログラムになります。

これを実行すると

新幹線の運行状況をイミディエイトに出力

とイミディエイトウィンドウに出力されます。なんか、いい感じに役立ちそうになってきました。

まとめ

HTMLでのテーブルの記述の仕組みについて触れつつ、WEB上のテーブル要素内のデータを取得する方法についてお伝えしてきました。

WEBスクレイピングにおいて、テーブル要素内のデータを取得したいというニーズはかなりありますので、今回のテクニックが役立つ機会も多いものと期待しています。

次回以降、さらに凝った取得の仕方についてお伝えできればと思います。

【エクセルVBAでIE操作】IEで検索窓にキーワードを入力して送信する方法
初心者向けエクセルVBAでIEを操作するシリーズです。今回はIEを操作してWEBページ内の検索窓に任意のキーワードを入力して送信する方法をお伝えします。GoogleChromeの検証機能も活用しますよ!

どうぞお楽しみに!

連載目次:エクセルVBAでIEを操作してWEBスクレイピング

IEを操作してWEBページのデータを取得して、エクセルのデータとして取り込む、つまりWEBスクレイピングをエクセルVBAで実現します。各種WEBページを課題として様々なデータの取得の仕方を解説していきたいと思います。
  1. 【エクセルVBAでIE操作】10分で終わるセッティングとWEBページの閲覧確認
  2. 【エクセルVBAでIE操作】HTMLタグと要素そしてドキュメントの取得
  3. 【エクセルVBAでIE操作】ブラウザの読み込み待ちをしないとダメなのです
  4. 【エクセルVBAでIE操作】ページ内のリンク先URLを全部取得する
  5. 【エクセルVBAでIE操作】ディスクリプションなどの要素をname属性でGetする
  6. 【エクセルVBAでIE操作】hタグなどの要素をタグ名でGetする
  7. 【エクセルVBAでIE操作】WEBページのテーブル要素を自動で取得する方法
  8. 【エクセルVBAでIE操作】IEで検索窓にキーワードを入力して送信する方法
  9. 【エクセルVBAでIE操作】ページをクロールしてブログの記事一覧を取得する方法
  10. 【エクセルVBAでIE操作】ブログの記事一覧ページから公開日とカテゴリを取得する
  11. 【エクセルVBAでIE操作】ページャーを最後のページまでどんどんリンクする
  12. 【エクセルVBAでIE操作】ユーザー名とパスワードを入力してログインをする

連載目次:データ一覧から請求書を自動で作る

お仕事において特定のデータ一覧から必要な情報を抽出するということは頻繁にありうると思います。ここではデータ一覧から請求書を作るということを目標に、実務で使えるスキルをまっすぐに身に着けることを目的としています。
  1. 【初心者向けエクセルVBA】データ一覧から請求書を自動で作る
  2. 【初心者向けエクセルVBA】ワークシートをオブジェクト名で取り扱う方法
  3. 【初心者向けエクセルVBA】For~Next文で簡潔にプログラムを書く
  4. 【初心者向けエクセルVBA】行の数をカウントする&不要な行を隠す
  5. 【初心者向けエクセルVBA】文字列の連結&Format関数での書式変更
  6. 【初心者向けエクセルVBA】セル範囲を一気にまとめてコピーする方法
  7. 【初心者向けエクセルVBA】ワークシートのデータのある範囲だけをピッタリ取得する方法
  8. 【初心者向けエクセルVBA】セル範囲の平行移動をする方法・リサイズをする方法
  9. 【初心者向けエクセルVBA】日付データから年・月・日を取り出す
  10. 【初心者向けエクセルVBA】If~Thenを使った条件分岐の超入門
  11. 【初心者向けエクセルVBA】For~Next文でセル範囲を一行ずつ移動させる
  12. 【初心者向けエクセルVBA】セル範囲のクリア~ClearContentsメソッドとClearメソッド
  13. 【初心者向けエクセルVBA】ワークシート・セルを選択する方法の色々について
  14. 【初心者向けエクセルVBA】入力ダイアログを表示するInputBoxメソッドの使い方
  15. 【初心者向けエクセルVBA】日付データから月末日と翌月末日を自動算出する
  16. 【初心者向けエクセルVBA】ワークシートをコピーする方法とそのシート名を変更する方法
  17. 【初心者向けエクセルVBA】オブジェクトを変数にセットして取り扱う方法
  18. 【初心者向けエクセルVBA】Openメソッドで新たなブックを開く方法
  19. 【初心者向けエクセルVBA】現在マクロを書いているブックのフォルダパスを取得する
  20. 【初心者向けエクセルVBA】開いたブックとそのワークシートをオブジェクト変数にセットする
  21. 【初心者向けエクセルVBA】ワークブックを別名で保存して閉じる方法
  22. 【初心者向けエクセルVBA】取引先別に請求書を作成するマクロを作る

  投稿者プロフィール

タカハシノリアキ株式会社プランノーツ 代表取締役
株式会社プランノーツ代表、コミュニティ「ノンプロ研」主宰。1976年こどもの日生まれ。東京板橋区在住。「ITで日本の『働く』の価値を上げる!」をテーマに、VBA&GASの開発、講師、執筆などをしております。→詳しいプロフィールはコチラ
★ご依頼・ご相談はお気軽にどうぞ!→お問い合わせはコチラ
★フォロー頂ければ嬉しいです。

コメント

  1. a より:

    確認なのですが。

    新幹線の運行状況をイミディエイトウィンドウに出力
    以上をまとめますと、こんなプログラムになります。

    ~

    下の行の表示は正常なのでしょうか?

    追伸。
    VBAの学習にて参考にさせて頂き、非常に助かっています。

  2. a より:

    迅速なご対応ありがとうございます m(_ _)m
    今後も、VBAの参考にさせて頂きます!!

  3. t より:

    たいへん わかりやすく 非常に助かっております。
    初歩的なことなのですが、エクセルシートに一覧を書き出すことができず、四苦八苦しております。イミディウインドウに出力されたものをどのようにエクセルシートに書き出すか、ご教授くだされば幸いです。

  4. しんかずま より:

    Set htmlDoc = objIE.document ‘objIEで読み込まれているHTMLドキュメントをセット
    「型が一致しません」と表示されます。

    • しんかずまさん

      コメントありがとうございます。

      そのエラーメッセージはその他の通り、変数の型と代入する値(またはSetするオブジェクト)の型が異なっている場合に出ます。
      変数htmlDocがHTMLDocument型で宣言されているかご確認いただくのが良いかと思います。

      • しんかずま より:

        タカハシ様
        早速のご回答ありがとうごぜいます。
        ブログに掲載されているサンプルプログラムを実行した結果、「型が一致しません」と出ます。宣言も正しいと思います。
        自作のプログラムで同じ現象が起きましたので、ぐぐってここに辿り着きました。
        1年ほど前は、この書き方でうまく処理できましたが、環境が変わったせいか、うまくいきません。
        書籍も参考にしましたが、書籍のサンプルプログラムで「型が一致しません」とでます。
        現在の環境は、Win7 ACCESS2013 です。
        何かご存知でしたら、ご教授下さい。

  5. 横山 登 より:

    しんかずま様
    横から誠に失礼します。
    VBA初心者のヨコヤマと申します。
    私も同じ経験をし、以下の手順で問題発生が消滅したので参考までにお報せします。
    なお、私の場合は本連載の “No.4 【エクセルVBAでIE操作】ページ内のリンク先URLを全部取得する”…で「」型が一致しないがでました。
    Dim宣言文はタカハシ様のコードをコピペしていて問題が無いと思います。

    私ははこの問題が自分特有の環境の性かもと推察していましたが、貴方様にも同様に発生しているみたいですね。

    (解決できた手順)
    1)VBE画面>ツール>オプション>”□変数の宣言を強制する。” のチェックを外す。(当然、マクロには、Option Explicit 宣言を入れない)
    2)15行目の先頭に”‘”を入れて htmlDoc の型宣言文を無視させる。
    3)実行すると、”?typename(htmlDoc)で型を調べると?typename(htmlDoc)…>HTMLdocument となり、set文で「型が一致しない」エラーは発生しませんし、当然処理もOKでした。
    ★自分の推察ですが、Dim文で型の宣言をしない事によりhtmlDocの型が暗黙のうちに Variantにされ、16行目の set文によって、htmlDoc の型が、HTMLDocument にセットされた為ではないでしょうか?
    ★なお、上記手順1)で、”□変数の宣言を強制する。” のチェックを入れて、2)で 15行目をコメントアウトしたままでも実行時にエラーになりませんでした。この為、このトラブルは自分環境特有の問題ではないかと推察した次第です。
    (以上です)