みなさん、こんにちは!
タカハシ(@ntakahashi0505)です。
エクセルVBAでInterneteExplorer(IE)を操作する初心者向けのシリーズですが、なんともう11回目になりました。
前回はこちらの記事。
このブログのトップページの記事一覧から
- 記事タイトル
- URL
- 公開日
- カテゴリ
をリストアップするプログラムを作成しました。
ですが実際は記事一覧はページャーによって複数のページにわたって掲載されています。
次のページも自動でクロールしたいですよね…
そんな悩みを解決すべく、今回はページャーを最後のページまで自動で移動するプログラムをご紹介します。
ページャーがどのように構成されているか検証をする
このブログはWordPressでできていまして、テーマはSimplicityを使っています。
Simplicityの記事一覧(インデックスリストといいます)において、ページャーがどのように構成されているか、Google Chromの検証機能で調べていきたいと思います。
次のページへのアンカーリンクを探す
まず、1ページ目のページャーですが
ここにありました。
class=”pagination”が付与されているul要素ですね。
各ページともclass=”pagination”が付与されているのは、ページャーだけですので
getElementsByClassName("pagination")(0)
で、つかむことができそうです。
この要素のouterHTMLをコピーして見てみますと
<ul class="pagination" role="menubar" aria-label="Pagination"> <li class="first"><a href="http://tonari-it.com/"><span>First</span></a></li> <li class="previous"><a href="http://tonari-it.com/"><span>Previous</span></a></li> <li class="current"><a>1</a></li> <li><a href="http://tonari-it.com/page/2/" class="inactive">2</a></li> <li><a href="http://tonari-it.com/page/3/" class="inactive">3</a></li> <li><a href="http://tonari-it.com/page/4/" class="inactive">4</a></li> <li><a href="http://tonari-it.com/page/5/" class="inactive">5</a></li> <li class="next"><a href="http://tonari-it.com/page/2/"><span>Next</span></a></li> <li class="last"><a href="http://tonari-it.com/page/13/"><span>Last</span></a></li> </ul>
と、左から順番にli要素で並んでいるようですね。
最後から二つ目の、class=”next”のli要素配下のアンカーが
href=”http://tonari-it.com/page/2/”
となっています。現在のページ数が1ですから、次のページは「~/page/2」ということですね。
これを踏んでいけば、次ページにどんどん行ってくれそうな気がしますね。
最後のページであることを判別するためのルールを見つける
最後のページに行ったときには、プログラムを終了しなければいけません。
最後のページである13ページ目のページャーがどのように構成されているか、検証で見てみましょう。
ここにあります。同じくclass=”pagination”のul要素です。
このouterHTMLも見てみましょう。
<ul class="pagination" role="menubar" aria-label="Pagination"> <li class="first"><a href="http://tonari-it.com/"><span>First</span></a></li> <li class="previous"><a href="http://tonari-it.com/page/12/"><span>Previous</span></a></li> <li><a href="http://tonari-it.com/page/9/" class="inactive">9</a></li> <li><a href="http://tonari-it.com/page/10/" class="inactive">10</a></li> <li><a href="http://tonari-it.com/page/11/" class="inactive">11</a></li> <li><a href="http://tonari-it.com/page/12/" class="inactive">12</a></li> <li class="current"><a>13</a></li> <li class="next"><a href="http://tonari-it.com/page/13/"><span>Next</span></a> </li><li class="last"><a href="http://tonari-it.com/page/13/"><span>Last</span></a></li> </ul>
最後から二つ目の、class=”next”のli要素配下のアンカーがどうなっているかというと
href=”http://tonari-it.com/page/13/”
となっています。
現在は13ページ目ですが、ここも「~/page/13/」となっています。
どうやら最後のページの場合は、現在のページ数と、class=”next”配下のアンカーの番号が等しくなるようです。
これを条件にストップしてあげればちゃんと止まってくれそうですね。
ページャーを順番にリンクしていくVBAプログラム
この検証を元に、プログラムを組んでみました。
こちらです。
Sub crawlPages() Dim objIE As InternetExplorer 'IEオブジェクトを準備 Set objIE = CreateObject("Internetexplorer.Application") '新しいIEオブジェクトを作成してセット objIE.Visible = True 'IEを表示 Dim strUrl As String '次ページのURL strUrl = "http://tonari-it.com" Dim htmlDoc As HTMLDocument 'HTMLドキュメントオブジェクトを準備 Dim elPage As IHTMLElement Dim strTmp As String Dim noNext As Long '次のページ数 noNext = 1 Dim i As Long '現在のページ数 i = 0 Do While i <> noNext '現在のページ番号と次ページの番号が異なっていれば繰り返す i = i + 1 objIE.navigate strUrl 'IEでURLを開く Do While objIE.Busy = True Or objIE.readyState < READYSTATE_COMPLETE '読み込み待ち DoEvents Loop Set htmlDoc = objIE.document 'objIEで読み込まれているHTMLドキュメントをセット Debug.Print htmlDoc.Title Set elPage = htmlDoc.getElementsByClassName("pagination")(0) 'class="pagination"の1つ目のul要素 'class="next"の1つ目のli要素の直下のaリンクを取得し"~/page/"までを削除 strTmp = Replace(elPage.getElementsByClassName("next")(0).FirstChild.href, "http://tonari-it.com/page/", "") noNext = Left(strTmp, Len(strTmp) - 1) '最後の"/"を削除し、次ページの番号を取得 strUrl = "http://tonari-it.com/page/" & noNext & "/" '次ページのURLを生成 Loop objIE.Visible = False 'IEを非表示 End Sub
Do Whileで最後のページになるまで繰り返す
27行目のDo Whileですが、現在のページ数iと次のページ数noNextが等しくない間のみ繰り返しをします。
iは繰り返しに入るたびに1ずつ加算されます。
noNextはページャー内のclass=”next”のli要素配下のアンカーリンクから抜き出してきた番号で、ここについては後ほど解説をします。
最後のページに到達した場合は、iとnoNextが両方とも13になり等しくなりますので、繰り返しに入らなくなります。
li要素の直下のhref属性からページ番号を取得する
40行目はいくつもの命令が組み合わさっていますが、まず
elPage.getElementsByClassName("next")(0)
で、class=”next”の1つ目のli要素を取得します。
elPage.getElementsByClassName("next")(0).FirstChild
により、そのli要素の直下の子要素であるa要素を取得
elPage.getElementsByClassName("next")(0).FirstChild.href
により、そのa要素のhref属性を取得ということになります。
Replace関数で”http://tonari-it.com/page/”を削除していますので、例えば3ページ目であれば、strTempは”3/”となります。
次に42行目の
noNext = Left(strTmp, Len(strTmp) - 1)
で、strTmpの長さより1少ない文字数分をLeftで切り出しますので、最後の”/”だけ取り除かれ、noNextは3となります。
実行結果
このプログラムを実行すると
と、ページャーをクロールしてすべてのページのタイトルがイミディエイトウィンドウに出力されます。
今回は、ページタイトルを表示するだけですが、このプログラムの35行目
Debug.Print htmlDoc.Title
の箇所に各ページで実行したい処理を入れればOKですね。
まとめ
以上、エクセルVBAでIEを操作してページャーを最後までクロールする方法についてお伝えしました。
ページャーの作りは各サイトで異なると思いますので、それぞれの構成を検証する必要がありますが、ページャーでのクロールが実現できるとスクレイピングの効率が爆発的に上がります。
ぜひ色々なパターンについて検証と実践を繰り返して、実力を上げていって頂ければと思います。
次回は、画像を取得する方法などをお伝えできればと思います。
どうぞお楽しみに!
連載目次:エクセルVBAをIEを操作して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などチャットでご相談に乗ります!
