Excel・VBA デキる解る!IE操作編 【全ページからデータを一括取得する方法】

この記事は約10分で読めます。

VBA操作編3回目 サムネイル

どうも、マサヤです!

この記事は、VBAでのIE操作が初めて or 慣れていない方向けに『Webサイト・システムの情報を取得・設定する方法』をお伝えしていく連載記事となってます!

 

前回はWebサイトの一ページから情報を取得する方法やHTMLの簡単な見方を紹介しました。

 

IE操作編 3回目は、Webサイト内の全ページから欲しい情報を一括で取得する方法をお伝えします!

もし、あなたがVBAでのIE操作が初めてなら、IE操作編の1回目から順に読んでくださいね。

本記事で習得できること

  • Webサイト内の全ページの情報を一括で取得できる方法。
  • ページ内のリンク(ボタン)をクリックする方法。

 

では、早速いきましょう!

 

スポンサーリンク

【動画】Webサイトの全ページから欲しい情報を一括取得

 

最初に動画で動きを確認しましょう!

VBA IE 全ページ内情報一括取得

 

ちょっとワチャワチャ(笑)してますが、一ページずつ移動して全ページのデータを取得しています。

処理としては、Webサイト(当ブログ)の全ページの記事カテゴリ、記事タイトル、記事URLを取得、その結果をExcelへ出力しています。

 

では、前回のコードと何が違うのか?

コードを見ていきましょう!

 

Webサイトの全ページからデータを取得するコード

 

コードはこちら!

Private Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal ms As Long)

Sub ieGetSiteData()

'IEオブジェクトを作成
Dim ie As InternetExplorer
Set ie = CreateObject("InternetExplorer.Application")

'開きたいURLを変数に代入
Dim strUrl As String
strUrl = "https://mmm-program.com/"

'IEを表示(見えるようにする)
ie.Visible = True

'指定したURLをIEで開く
ie.Navigate strUrl

'サイトの読み込みが完了するまで待つ
Do While ie.Busy = True Or ie.readyState <> READYSTATE_COMPLETE
    DoEvents
Loop

'Excelの行カウント変数
rowCnt = 3

'文章が長くなるためHTMLコレクションを変数へ格納
Set ieDoc = ie.document

'次へ(次ページ)が無くなるまで処理を繰り返す
Do
    'ページ内の記事数を取得
    postCnt = ieDoc.getElementById("main").getElementsByClassName("entry-card-wrap").Length
    
    '長いの変数に格納 可読性を高めるため
    Set posts = ieDoc.getElementById("main").getElementsByClassName("entry-card-wrap")
    
    '上記で取得した記事数分処理を繰り返す ※カウントは0から始まるため-1する
    For i = 0 To postCnt - 1
        '記事カテゴリを取得してExcelへ出力
        Cells(rowCnt, 2) = posts(i).getElementsByClassName("cat-label")(0).innerText
        '記事タイトルを取得してExcelへ出力
        Cells(rowCnt, 3) = posts(i).getElementsByClassName("entry-card-title card-title e-card-title")(0).innerText
        '記事URLを取得してExcelへ出力
        Cells(rowCnt, 4) = posts(i).getAttribute("href")
        
        'Excelへ出力行を次の行へ
        rowCnt = rowCnt + 1
    Next
    
    '次へのリンクが存在するか確認し、無ければ繰り返しを終了し、存在すれば次へのリンクをクリック。
    If ieDoc.getElementsByClassName("pagination-next-link key-btn")(0) = "" Then
        '次ページのリンクがないため繰り返しを抜ける(終了)
        Exit Do
    Else
        '次へのリンクをクリックし、次のページへ移動
        ieDoc.getElementsByClassName("pagination-next-link key-btn")(0).Click
        '待機:クリック後1秒待つ処理。
        Sleep 2000
        'サイトの読み込みが完了するまで待つ
        Do While ie.Busy = True Or ie.readyState <> READYSTATE_COMPLETE
            DoEvents
        Loop
    End If
Loop

'オブジェクトを閉じる
ie.Quit

'メモリからオブジェクトを破棄
Set ie = Nothing
 
End Sub

 

前回コードを基本使っていますが、いくつか変更と追加をしています。

それでは、一つずつ見ていきましょう。

 

次ページのリンク有無で条件分岐させる

 

今回の一番の肝である、次ページのリンクが有るのか無いのかの条件分岐です。

if分の中の処理は後で解説します。※コード:53行目
'次へのリンクが存在するか確認し、無ければ繰り返しを終了し、存在すれば次へのリンクをクリック。
If ieDoc.getElementsByClassName("pagination-next-link key-btn")(0) Is Nothing Then
'・・・省略
Else
'・・・省略
End If

 

ポイントはNothig使う

この条件分岐でポイントとなるのがNothingを使っている点です。

次ページリンクのクラス名であるpagination-next-link key-btnを、getElementsClassNameで取得しています。

存在すればHTMLコレクションが、存在しない場合はFalse・空白・NullとかではなくNothingが返されます。

そのため、下記のようなIF文を書くとエラーになるので注意しましょう。

If ieDoc.getElementsByClassName("pagination-next-link key-btn")(0) = False
If ieDoc.getElementsByClassName("pagination-next-link key-btn")(0) Is Null
if ieDoc.getElementsByClassName("pagination-next-link key-btn")(0) = ""

 

条件分岐(IF文)しないとエラーが発生

条件分岐が行わないと、プログラムはどのページでも次ページのリンクをクリックします。

その結果、最後のページでも次ページリンクをクリックし、エラーを発生させることになります。

これを回避するため、現在開いているページに次ページのリンク有無を確認する必要があるわけです。

 

スポンサーリンク

Clickで次のページへ移動する

 

前途の条件分岐で次ページのリンクが存在していたら、そのリンクをクリックさせます。

リンクやボタンをクリックする際は、Clickメソッドを使います。

※コード:58行目
'次へのリンクをクリックし、次のページへ移動
ieDoc.getElementsByClassName("pagination-next-link key-btn")(0).Click

リンクだけでなく、ボタン・ラジオボタン・チェックボックにもClickメソッドは使えます。

左クリック一発のものはClickで対外いけちゃいます)笑

 

Sleepでプログラム実行を一定時間待機させる

 

IE操作編においてSleepは結構重要なので、ガッツリ説明してます。

私が以前苦労したので同じ経験をしてほしくない!という思いで書いたら、長くなっちゃいました)笑

 

Sleepメソッドは、指定した時間(ミリ秒単位で指定)を待機させることできます。

下記コードでは2秒間(2000ミリ秒)待機させています。

※コード:60行目
'待機:クリック後1秒待つ処理。
Sleep 2000

 

Sleep使用には、WindowsAPIの宣言が必要

SleepはWindows APIの一つのため、使用するにはコードの一番上に下記を記載する必要があります。

※コード:1行目 利用PCの32bitの場合は、コード内のPtrsafeを削除すればOKです。
Private Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal ms As Long)

 

Busyメソッドの前に、Sleep(待機)が必要な理由

Clickメソッド直後にSleepを使って待機させている理由は、リンクをクリックして、ブラウザが次ページ読込開始するまでの時間を待つためです。

「あれ?それは次のコードにあるBusy等で対処するんじゃないの?」

と、思っているかもしれません。

 

混合しがちなのですが、Busyが受け持つのは読み込みを開始した後になります。

なので、読み込み開始していない状態でBusyコードにプログラムが到達すると、Busy = Falseとなるためプログラムが次の工程へと進んでしまいます。

結果として、エラーや同じページの情報を重複して取得するといった問題が発生します。

これを回避するため、ページ遷移が発生するコードの後にはSleepを差し込む必要があります。

 

Sleepは動作環境で不要になる場合もある

また、Sleepで指定する秒数に関しても注意が必要です。

PC・ネット環境によりPCの読込速度などが変動するため、2秒ではなく1秒で良い場合やSleepがそもそも不要になる場合もあります。

利用する際は、実際の動作環境で確認しながら調整しましょう。

 

リンクが存在しない場合はDoを抜ける

 

条件分岐で次ページのリンクが存在しない場合。

プログラムは最終ページと判断して、下記コードでDoループを抜けます。

※コード:55行目
'次ページのリンクがないため繰り返しを抜ける(終了)
Exit Do

 

ここはシンプルですね。

Do~Loop(32~66行目)で囲むことで、ページ毎の処理を繰り返し実行しています。

そして、ページ処理の最後に次ページリンク有無を確認、存在しなければ最終ページと判断しDoを抜けています。

Doを条件なしで使用しているので、Exitで抜けない限りは無限ループとなります。
PCが固まる可能性があるため、忘れずにExit Doしましょう。

 

スポンサーリンク

まとめ

 

IE操作編の3回目 Webサイトの全ページからデータを一括取得する方法をお伝えしました。

今回のコードを流れをまとめると下記になります。

◆処理の流れ

  1. ページ毎の処理を繰り返す。
  2. ページ毎の処理の最後に、次ページリンクの存在有無を確認。
  3. リンクが存在すれば、次ページリンクをクリックして1に戻る。
  4. リンクが存在しなければ、繰り返しを抜けて処理を終了する。

 

今回でWebサイトから欲しい情報を漏れなく取得できるようになったかと思います。

前途のコードをカスタマイズすれば、アルバイトサイトの情報取得して、全国・エリア別など様々な角度から平均時給や募集件数などを計算したり、ショッピングサイトから商品名と価格等を取得して価格相場を調べたりと、アイディア次第で色々できますよ。

 

かなり実用的になってきましたね。

次回(IE操作編3回目)は、より実用的にするためWebサイトへのデータ設定をお伝えします!

これにより、検索バーに検索ワードを入力・検索、結果の情報を取得したり、Webシステムへのデータへ入力し登録、ログイン画面へのログイン等々、より様々なことができるようになります。

コメント