Internet Explorereはサポートが終了します!
マイクロソフトからIEのサポート終了が発表されています。
サポートが終了すると、脆弱性が見つかったときなど適切なアップデートが行われず、危険に晒される可能性があります。
またウェブページによっては正しく表示されなくなる可能性があります。
この記事は残しておきますが、非推奨になる可能性があります。
はじめに
↓の記事では記事タイトルをひとつ取得するところまで実装しました。
ぜひ↑もご参照頂ければ幸いです。
この記事ではページを遷移して、すべての記事タイトルを取得することが目的です。
上述の記事で紹介したコードはこんな感じでした(ieの処理待ち部分を関数に外出ししました)。
Sub sample() Dim ie As InternetExplorer: Set ie = New InternetExplorer ie.Visible = True ie.Navigate "https://www.tekizai.net/" waite ie Dim htmlDoc As HTMLDocument: Set htmlDoc = ie.Document Dim htmlAnc As HTMLAnchorElement Set htmlAnc = htmlDoc.getElementsByClassName("entry-title-link").Item(0) Debug.Print htmlAnc.innerText Set ie = Nothing End Sub Function waite(ie As InternetExplorer) As Boolean Do While (ie.Busy Or ie.ReadyState <> READYSTATE_COMPLETE) DoEvents Loop waite = True End Function
htmlDoc.getElementsByClassName("entry-title-link").Item(0) を HTMLAnchorElementに割り当てることで、innerTextメソッドを呼び出したのでした。
ここまでできていれば、あとは次ページにアクセスして次ページがなくなるまで同じことを繰り返すだけです。
次ページをクリックする
「次のページ」のリンクを見てみます。
このリンクのHTMLソースを見てます。
該当箇所の抜粋です。
<div class="pager autopagerize_insert_before"> <span class="pager-next"> <a href="https://www.tekizai.net/?page=1563706375" rel="next">次のページ</a> </span> </div>
次のページは、aタグで、innnerTextが「次のページ」になっています。
残念ながらclass属性はありません。
getElementsByClassNameメソッドが使えない・・・。
今度は別の方法でaタグを取得してみましょう。
classやidがない場合のタグの取得方法
classやidがない場合は、getElementsByTagNameというメソッドを使って要素を取得することができます。
innerTextをイミディエイトウィンドウに出力してみます。
Sub sample() Dim ie As InternetExplorer: Set ie = New InternetExplorer ie.Visible = True ie.Navigate "https://www.tekizai.net/" waite ie Dim htmlDoc As HTMLDocument: Set htmlDoc = ie.Document Dim htmlAnc As HTMLAnchorElement: Set htmlAnc = htmlDoc.getElementsByTagName("a").Item(0) Debug.Print htmlAnc.innerText End Sub Function waite(ie As InternetExplorer) As Boolean Do While (ie.Busy Or ie.ReadyState <> READYSTATE_COMPLETE) DoEvents Loop waite = True End Function
「スマートフォン用の表示で見る」が出力されました。
HTMLソースにはあるけど、表示していないやつです。
わかりづらいやつが例で出てきてしまいましたが、まぁしょうがない。
こんな調子で、aタグを取得することができました。
次は、このgetElementsByTagNameで取得できた要素を逐一調べて、innerTextが「次のページ」に一致したものがゲットしたいaタグです。
全ての要素にアクセスする
全ての要素にアクセスするためには、For each でアクセスするのが簡単です。
こんな感じになります。
Sub sample() Dim ie As InternetExplorer: Set ie = New InternetExplorer ie.Visible = True ie.Navigate "https://www.tekizai.net/" waite ie Dim htmlDoc As HTMLDocument: Set htmlDoc = ie.Document Dim htmlAnc As HTMLAnchorElement For Each htmlAnc In htmlDoc.getElementsByTagName("a") If htmlAnc.innerText = "次のページ" Then htmlAnc.Click End If Next htmlAnc End Sub Function waite(ie As InternetExplorer) As Boolean Do While (ie.Busy Or ie.ReadyState <> READYSTATE_COMPLETE) DoEvents Loop waite = True End Function
勢い余ってクリックまでしてしまいました。
実際に動かしてみると、クリックされ、次ページに遷移しました。
クリックする場合はHTMLAnchorElementのClickメソッドを呼び出します。
ちなみにHTMLAnchorElement要素以外のHTM要素ならどれでもClickメソッドを呼び出すことができます。
これで任意のaタグを取得することができました。
また、次ページまで遷移することができたので、これをひたすら繰り返して記事のタイトルをすべて取得する目途が立ちました。
今度は、クリックについてもう少し理解を深めるために、単純に最後のページまで遷移するプログラムを作ってみましょう。
最初から最後のページまで遷移する
最初から最後のページまで遷移する処理の流れを考えてみます。 こんな流れでしょうか。
Sub sample() Dim ie As InternetExplorer: Set ie = New InternetExplorer ie.Visible = True 'トップページにアクセスする ie.Navigate "https://www.tekizai.net/" waite ie '次ページのaタグがあるかどうかの判定結果 Dim hasAtag As Boolean Dim htmlAnc As HTMLAnchorElement Do While True Dim htmlDoc As HTMLDocument: Set htmlDoc = ie.Document hasAtag = False ’次ページのaタグがあるか? For Each htmlAnc In htmlDoc.getElementsByTagName("a") If htmlAnc.innerText = "次のページ" Then ’aタグをクリック htmlAnc.Click 'aタグがあったのでtrueに hasAtag = True Exit For End If Next htmlAnc ’aタグがない場合、処理終了 If hasAtag = False Then Exit Do End If waite ie Loop Set ie = Nothing End Sub Function waite(ie As InternetExplorer) As Boolean Do While (ie.Busy Or ie.ReadyState <> READYSTATE_COMPLETE) DoEvents Loop waite = True End Function
Do whileでtrueになるまでループします。
Exit Doが呼び出されるまでループします。
変数hasAtagがfalse、つまり該当のaタグが見つからなかった場合に抜けだします。
これを実行すると、矢継ぎ早にieの画面が最終ページまで遷移します。
あとは、この途中で各ページの記事タイトルを取得するだけです。
先ほどのフローに一つだけ処理が追加されます。こんなイメージでしょうか。
記事のタイトルを取得する処理が加わりました。
記事のタイトルはイミディエイトウィンドウに出力するようにしましょう。
コード的には、コメントの箇所に新たに処理を追加します。
Sub sample() Dim ie As InternetExplorer: Set ie = New InternetExplorer ie.Visible = True 'トップページにアクセスする ie.Navigate "https://www.tekizai.net/" waite ie '次ページのaタグがあるかどうかの判定結果 Dim hasAtag As Boolean Dim htmlAnc As HTMLAnchorElement Do While True Dim htmlDoc As HTMLDocument: Set htmlDoc = ie.Document 'ここで全ての記事タイトルを取得する処理 getTitle htmlDoc hasAtag = False '次ページのaタグがあるか? For Each htmlAnc In htmlDoc.getElementsByTagName("a") If htmlAnc.innerText = "次のページ" Then 'aタグをクリック htmlAnc.Click 'aタグがあったのでtrueに hasAtag = True Exit For End If Next htmlAnc 'aタグがない場合、処理終了 If hasAtag = False Then Exit Do End If waite ie Loop Set ie = Nothing End Sub Function waite(ie As InternetExplorer) As Boolean Do While (ie.Busy Or ie.ReadyState <> READYSTATE_COMPLETE) DoEvents Loop waite = True End Function ’全ての記事タイトルを取得する処理 Sub getTitle(htmlDoc As HTMLDocument) Dim htmlAnc As HTMLAnchorElement For Each htmlAnc In htmlDoc.getElementsByClassName("entry-title-link") Debug.Print htmlAnc.innerText Next htmlAnc End Sub
これまでの解析から、次ページはClass="entry-title-link"で定義されていることがわかっています。
そのため、先ほどのaタグと同じ要領でfor eachですべての要素にアクセスし、イミディエイトウィンドウに出力します。
実行してみると、全ての記事タイトルがイミディエイトウィンドウに出力されました。
ただ記事タイトルを取得するだけでもなんだか長くなってしまいました。
スクレイピングは結構地道なものです・・・。
ということで、今回はここまでにします。
↓で最後になります。インプットボックスへの書き込みについてを見ていきたいと思います。ぜひご参照頂ければ幸いです。
ここまでお読みいただき、ありがとうございました。