みなさん、こんにちは!
JR東日本さんにはかなりお世話になっています、タカハシ(@ntakahashi0505)です。
初心者向けエクセルVBAでIEを操作するシリーズです。今回はだいぶ本格的なWEBスクレイピングをしていきますよ。
前回はこちらの記事で
getElementsByTagNameを使って、特定のHTML要素をタグ名で取得する方法についてお伝えしました。
今回はこれをさらに応用してWEB上の「表」つまり、テーブル要素を取得していきたいと思います。
なにせ、WEBスクレイピングで欲しいのはデータの場合が圧倒的に多いですよね?そしてそのデータは「表」つまりテーブル要素にまとまっている場合が多いわけです。
その方法を知ってしまえば、WEBスクレイピングはかなり制覇したといっても良いのでは?!
ということで早速いってみましょう!
目次 [閉じる]
前回のおさらい
前回のプログラムはこちらです。
開いたページのヘッダー要素h1~h3をそれぞれ取得してイミディエイトウィンドウに表示するという内容でした。
getElementsByTagNameでタグ名(h1~h3)を指定することで、該当のHTML要素をコレクションとして取得することができます。
今回はgetElementsByTagNameを使用してテーブル要素をガッツリつかんでいきたいと思います。
HTMLのテーブル要素の仕組み
今回はまたJR東日本さんのページにお手伝い頂きます。このページです。
JR東日本管轄の新幹線の運行状況のお知らせページですが、運行状況はテーブルで表現されています。
現在は全て平常運転ですね。
なんで、東海道新幹線がないんだ!?って思われるかも知れませんが、お察しください。JR東日本の新幹線はこの5本なのです。
さて、この表がHTMLではどのように表現されているかを見てみましょう。Google ChromeでHTMLソースを見る場合は ctrl + u
でしたね。
HTMLでの表はテーブルタグ<table>~<table>内に記載をします。
このページにはtableタグは1セットのみなのですが、そのtableタグ内はけっこう色々な要素が含まれていてわりとボリュームがありますね。
よく見ますと
このように、同じような構造のtrという要素が5つ分で成り立っているようです。
1つ目のtr要素の中には、thという要素があって「東北新幹線」、tdという要素の中にさらにimg要素があってそのalt属性に「平常運転」、あと「 」が挟まっている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タグの中にあります。
手順としては
- tr要素の中からth要素をコレクションとして取得
- その1番目のth要素(といっても要素数は1つしかありませんが)からテキストを取り出す
という手順になります。
thコレクションを格納するオブジェクト変数をcolTHとします。要素内のテキストを取得するにはinnerTextを使いますから
とすればOKです。コレクション内の要素には登場順に0から採番されますから、colTH(0)はコレクションcolTHの1番目の要素という意味でしたね。
これで新幹線名はGet完了です。
td要素をコレクションとして取得してimgタグのalt属性を取り出す
次が少し難しそうですね。
先ほどの例を参考にすると手順としては
- tr要素の中からtd要素をコレクションとして取得
- その1番目の要素からimg要素をコレクションとして取得
- 取得したimg要素からalt属性を取得
としても良いのですが、実は
- tr要素の中からimg要素をコレクションとして取得
- その1番目のimg要素(といっても要素数は1つしかありませんが)からalt属性を取り出す
というように、わざわざtdをつかまなくてもその下のimgを直接取りに行っちゃってもOKです。
imgコレクションを格納するオブジェクト変数をcolImgとします。要素内の属性を取得するにはそのまま属性名altで取り出せますから
とします。これで運行状況も取得できました。
td要素をコレクションとして取得してその2番目の要素のテキストを取り出す
運行状況が正常ですと詳細が全く表示されないのでつまらないと言えばつまらないのですが、平和で何よりです。
何も表示はされていないのですがHTMLソース内には「 」と記載されています。これは何かと言いますと「半角スペース」なのですが、実はいわゆる普通の半角スペースとは異なる特別な半角スペースなんですって。
今回に限ってはそんなにプログラムに影響があるわけではないので、特に気にせずに進めますね。
で、この詳細情報の取得に関しては、これまでの例に倣えば簡単ですね。
手順としては
- tr要素の中からtd要素をコレクションとして取得
- その2番目のtd要素からテキストを取り出す
という手順になります。
tdコレクションを格納するオブジェクト変数をcolTDとしますと
とすればOKですね。コレクション要素は0から採番されますから、2番目の要素が欲しいときはcolTD(1)で取得できます。
新幹線の運行状況をイミディエイトウィンドウに出力
以上をまとめますと、こんなプログラムになります。
これを実行すると
とイミディエイトウィンドウに出力されます。なんか、いい感じに役立ちそうになってきました。
まとめ
HTMLでのテーブルの記述の仕組みについて触れつつ、WEB上のテーブル要素内のデータを取得する方法についてお伝えしてきました。
WEBスクレイピングにおいて、テーブル要素内のデータを取得したいというニーズはかなりありますので、今回のテクニックが役立つ機会も多いものと期待しています。
次回以降、さらに凝った取得の仕方についてお伝えできればと思います。
どうぞお楽しみに!
連載目次:エクセルVBAをIEを操作してWEBスクレイピング
IEを操作してWEBページのデータを取得して、エクセルのデータとして取り込む、つまりWEBスクレイピングをエクセルVBAで実現します。各種WEBページを課題として様々なデータの取得の仕方を解説していきたいと思います。- 【エクセルVBAでIE操作】10分で終わるセッティングとWEBページの閲覧確認
- 【エクセルVBAでIE操作】HTMLタグと要素そしてドキュメントの取得
- 【エクセルVBAでIE操作】ブラウザの読み込み待ちをしないとダメなのです
- 【エクセルVBAでIE操作】ページ内のリンク先URLを全部取得する
- 【エクセルVBAでIE操作】ディスクリプションなどの要素をname属性でGetする
- 【エクセルVBAでIE操作】hタグなどの要素をタグ名でGetする
- 【エクセルVBAでIE操作】WEBページのテーブル要素を自動で取得する方法
- 【エクセルVBAでIE操作】IEで検索窓にキーワードを入力して送信する方法
- 【エクセルVBAでIE操作】ページをクロールしてブログの記事一覧を取得する方法
- 【エクセルVBAでIE操作】ブログの記事一覧ページから公開日とカテゴリを取得する
- 【エクセルVBAでIE操作】ページャーを最後のページまでどんどんリンクする
- 【エクセルVBAでIE操作】ユーザー名とパスワードを入力してログインをする
連載目次:データ一覧から請求書を自動で作る
お仕事において特定のデータ一覧から必要な情報を抽出するということは頻繁にありうると思います。ここではデータ一覧から請求書を作るということを目標に、実務で使えるスキルをまっすぐに身に着けることを目的としています。- 【初心者向けエクセルVBA】データ一覧から請求書を自動で作る
- 【初心者向けエクセルVBA】For~Next文で簡潔にプログラムを書く
- 【初心者向けエクセルVBA】行の数をカウントする&不要な行を隠す
- 【初心者向けエクセルVBA】文字列の連結&Format関数での書式変更
- 【初心者向けエクセルVBA】If~Thenを使った条件分岐の超入門
- 【初心者向けエクセルVBA】Public変数の宣言とSubプロシージャの呼び出し
- 【初心者向けエクセルVBA】InputBoxでの日付入力と月末日の自動算出
- 【初心者向けエクセルVBA】Worksheetのコピーを活用して複数の請求書を作る
- 【初心者向けエクセルVBA】ファイルのコピーを使って取引先別の請求書を作る
- エクセルVBAでDateAdd関数を使って年月を条件としてSumIfs関数を使う方法
- 宣言もセットも不要!エクセルVBAでワークシートをオブジェクト名で取り扱う方法
- エクセルVBAでシートの列の挿入も簡単に対応できちゃう列挙体の使い方
コメント
確認なのですが。
新幹線の運行状況をイミディエイトウィンドウに出力
以上をまとめますと、こんなプログラムになります。
~
下の行の表示は正常なのでしょうか?
追伸。
VBAの学習にて参考にさせて頂き、非常に助かっています。
プログラムの箇所の表示が崩れてしまっていましたね…。
ご指摘ありがとうございます。
修正を致しました!
迅速なご対応ありがとうございます m(_ _)m
今後も、VBAの参考にさせて頂きます!!
たいへん わかりやすく 非常に助かっております。
初歩的なことなのですが、エクセルシートに一覧を書き出すことができず、四苦八苦しております。イミディウインドウに出力されたものをどのようにエクセルシートに書き出すか、ご教授くだされば幸いです。
いつもご覧いただきましてありがとうございます。
ご質問の件は、こちらの記事をご参考頂ければと思います。
https://tonari-it.com/excel-vba-invoice/
またその他お知りになりたいことがあった場合は、以下に記事まとめページを作成しておりますので、合わせてご覧いただければ幸いです。
今後も弊ブログをどうそよろしくお願いいたします。
Set htmlDoc = objIE.document ‘objIEで読み込まれているHTMLドキュメントをセット
「型が一致しません」と表示されます。
しんかずまさん
コメントありがとうございます。
そのエラーメッセージはその他の通り、変数の型と代入する値(またはSetするオブジェクト)の型が異なっている場合に出ます。
変数htmlDocがHTMLDocument型で宣言されているかご確認いただくのが良いかと思います。
タカハシ様
早速のご回答ありがとうごぜいます。
ブログに掲載されているサンプルプログラムを実行した結果、「型が一致しません」と出ます。宣言も正しいと思います。
自作のプログラムで同じ現象が起きましたので、ぐぐってここに辿り着きました。
1年ほど前は、この書き方でうまく処理できましたが、環境が変わったせいか、うまくいきません。
書籍も参考にしましたが、書籍のサンプルプログラムで「型が一致しません」とでます。
現在の環境は、Win7 ACCESS2013 です。
何かご存知でしたら、ご教授下さい。