いわゆるWebスクレイピングのようなことをやろうとしています。
IEウィンドウを操作して特定のWebサイト上で決まったメニュー操作を行い、表示された情報を取得する作業です。
実際に作成したコードを走らせると途中で**「HRESULT からの例外」**エラーが発生して処理が止まってしまいます。
このエラーへの対処法についての質問です。
エラー発生状況を以下に箇条書きします。
- 全く同じ条件で同じコードを走らせても、エラーが出るときと出ない時がある。
- エラーが出る箇所も毎回異なる。
- 出るエラーも毎回異なる。
- ただし、すべて「HRESULT からの例外:0x????????」形式のエラーで出ている(?は数字)
- エラーが出てから再度[続行]で進めても同じエラーで先へ進めない(つまり実施タイミングの問題ではない?)
コードの一例を以下に記載します。(下記以外のコードでもエラーは出ます)
lang
1Option Explicit On 2 3Module Module1 4 Public Sub Main(ByVal targetURL As String) '引数に対象URLを入れて実施する 5 Dim objIE As Object 6 objIE = CreateObject("InternetExplorer.Application") 7 objIE.Visible = False '←★ここでエラーが出る場合もある。 8 objIE.navigate(targetURL) 9 10 Do '「次のページ」ボタンのループ 11 Call IEWait(objIE) 12 13 'ページ内の全要素検索 14 For Each one_tag In objIE.document.all 15 If UCase(one_tag.TagName) = UCase("a") Then 16 Debug.Print(one_tag.href) '該当リンクアドレスを取得 17 End If 18 Next 19 Loop While Ichiran_Tugihe(objIE) '「次のページ」ボタンを押す 20 21 'IE終了 22 objIE.Quit 23 objIE = Nothing 24 End Sub 25 26 27 'IEを待機する関数 28 Private Sub IEWait(ByRef objIE As Object) 29 Do While objIE.busy = True Or objIE.readystate <> 4 30 System.Windows.Forms.Application.DoEvents() 31 Loop 32 End Sub 33 34 '「次のページ」ボタンを押すスクリプト 35 Private Function Ichiran_Tugihe(ByRef objIE As Object) As Boolean 36 Dim i As Long 37 Ichiran_Tugihe = False 38 39 For i = 0 To objIE.document.links.length - 1 '←★追加情報:HRESULT からの例外:0x800A01B6エラーが出たりでなかったり 40 If objIE.document.links(i).title = "次のページ" Then 41 Ichiran_Tugihe = True 42 objIE.document.links(i).Click 'クリック 43 Call IEWait(objIE) 44 Exit For 45 End If 46 Next 47 End Function 48 49End Module 50
●発生するエラー:
上記コードで最もよく発生するエラーは下記です。
型 'System.NotSupportedException' のハンドルされていない例外が Microsoft.VisualBasic.dll で発生しました
追加情報:HRESULT からの例外:0x800A01B6
このエラーを控えた際はFor i = 0 To objIE.document.links.length - 1
部分で発生していましたが、他の部分でも出たりでなかったりします。
上記より発生頻度は低い気がしますが、下記も出ます。
型 'System.Runtime.InteropServices.COMException' の例外が Microsoft.VisualBasic.dll で発生しましたが、ユーザー コード内ではハンドルされませんでした
追加情報:リモート プロシージャ コールに失敗しました。 (HRESULT からの例外:0x800706BE)
これはobjIE.Visible = False
で出ました。
●試したこと:
Dim objIEdoc As mshtml.HTMLDocument = DirectCast(objIE.document, mshtml.HTMLDocument)
を使って、objIEに対して実施していたコマンドをobjIEdocに置き換える
→ 心なしかエラー発生率は下がった気がしますが、やはり同様のエラーが出ることがあります。
- Form上にWebBrowserオブジェクトを配置し、
objIE = Form1.WebBrowser1
コードを配置する
→ WebBrowserとIEの動作仕様が違うのか、JavaScript絡みのエラーダイアログが頻発してどのサイトも正常動作せず。
- 各プロシージャ内にTry~Catchを使って無理やりエラー回避することは一応は可能です。
lang
1Dim Retry As Boolean = True 2Dim objIE As Object 3objIE = CreateObject("InternetExplorer.Application") 4 5Do While Retry = True 6 Try 7 ' 8 'ここに実施するコードを入れる。 9 ' 10 Retry = False 11 Catch ex As System.Exception 12 objIE.Quit 13 objIE = Nothing 14 objIE = CreateObject("InternetExplorer.Application") 15 End Try 16Loop
開発、テスト環境:
Win10x64 1709
Internet Explorer 11
Visual Studio Community 2015
補足です。
今回、エラーコードを基に調べてみたところ「原因はわからないけどこうすれば直った」と言う旨の話が何件かあり、それを基に**「●試したこと:」**を実施していますが、解決していません。
前述の通り、エラー発生時にエラーをcatch
してから再度同じ処理を実施すれば今度はエラーが出ずに継続できますが、何回かに一回、全く同じ場所で同じエラーが出続けて無限ループすることがあることがわかりました。
Form側のコードを下記のようにし、メインの処理をスレッドに分けて、一定期間処理が終わらなければ無理やりスレッドごと処理を中断し、その後再開すると言う方法を試してみました。しかし、この方法で処理を再実行しても全く同じ場所で同じエラーが出て進めません。
試しに[ielowutil]プロセスも終了するようにしてみましたが、同様でした。
しかし、手動で[デバッグの停止]を実施して、再度プログラムを開始して同じURLを処理すると正常に機能します。
lang
1Option Explicit On 2 3Public Class Form1 4 5 Private t As New System.Threading.Thread( 6 New System.Threading.ParameterizedThreadStart(AddressOf Main)) 7 8 Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click 9 10 LastAct = Now 11 Me.Timer1.Enabled = True 12 t.Start(Me.TextBox1.Text) '入力されたURL内のリンクを調べる 13 14 End Sub 15 16 '一定期間応答がなければ強制的にスレッドを立ち上げなおす 17 Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick 18 '10分以上応答なければ強制再実行 19 If DateDiff("n", LastAct, Now) > 10 Then 20 Me.Timer1.Enabled = False 21 Debug.Print("10分応答なし") 22 t.Abort() 23 t.Join() 24 KillProcess("iexplore") 'iexploreのプロセスを強制終了するコマンド 25 LastAct = Now 26 t = Nothing 27 t = New System.Threading.Thread( 28 New System.Threading.ParameterizedThreadStart(AddressOf Main)) 29 t.Start(Me.TextBox1.Text) 30 Me.Timer1.Enabled = True 31 End If 32 End Sub 33End Class

回答3件
あなたの回答
tips
プレビュー