3

ベンダー情報のために会社の内部SAPサイトをスクレイプするマクロを書いています。いくつかの理由で、VBAを使用する必要があります。ただし、ページをスクレイプしようとすると、なぜこれら3つのエラーが発生し続けるのか理解できません。これがUAC整合性モデルと関係がある可能性はありますか?または、私のコードに何か問題がありますか?httpを使用するWebページをInternetExplorerで別の方法で処理できる可能性はありますか?他の内部Webページも含めて、どのWebページにもアクセスでき、それぞれをうまくスクレイプできます。しかし、SAPページをスクレイプしようとすると、これらのエラーが発生します。エラーの説明と発生時期は次のとおりです。

800706B5-インターフェイスが不明です(問題のあるコードを実行する前にブレークポイントを設定すると発生します)

80004005-不特定のエラー(エラーを配置せずにマクロを実行した場合に発生します)

80010108-呼び出されたオブジェクトがクライアントから切断されました。(このエラーが一貫して発生するようには見えません。Excelの何かが破損しているためにページが読み込まれず、Excelを再インストールする必要がある頃に発生するようです)

何が起こっているのか全くわかりません。整合性ページは私にはあまり意味がありませんでした、そしてこれで私が見つけたすべての研究はデータベースへの接続とADOとCOM参照の使用について話しました。ただし、私はInternetExplorerを介してすべてを行っています。これが私の関連するコードです:

Private Sub runTest_Click()
   ie.visible = True
   doScrape
End Sub
'The code to run the module
Private Sub doTest()
   Dim result As String
   result = PageScraper.scrapeSAPPage("<some num>")
End Sub

PageScraperモジュール

Public Function scrapeSAPPage(num As Long) As String
   'Predefined URL that appends num onto end to navigate to specific record in SAP
   Dim url As String: url = "<url here>" 
   Dim ie as InternetExplorer
   set ie = CreateObject("internetexplorer.application")
   Dim doc as HTMLDocument

   ie.navigate url 'Will always sucessfully open page, regardless of SAP or other
   'pauses the exection of the code until the webpage has loaded
   Do
     'Will always fail on next line when attempting SAP site with error
     If Not ie.Busy And ie.ReadyState = 4 Then 
        Application.Wait (Now + TimeValue("00:00:01"))
        If Not ie.Busy And ie.ReadyState = 4 Then
           Exit Do
        End If
     End If
     DoEvents
   Loop

   Set doc = ie.document 'After implementation of Tim Williams changes, breaks here
   'Scraping code here, not relevant

 End Function

Windows7マシンでIE9とExcel2010を使用しています。あなたが提供できるどんな助けや洞察も大いにありがたいです。ありがとうございました。

4

1 に答える 1

3

私はこのタイプのスクレイピングを頻繁に行っていますが、IEの自動化を100%確実に機能させることは非常に困難であり、あなたが見つけたようなエラーが発生します。これらはタイミングの問題であることが多いため、ステップスルー時に表示されず、ライブ実行中にのみ表示されるため、デバッグが非常にイライラする可能性があります。エラーを最小限に抑えるために、次の手順を実行します。

より多くの遅延を導入します。ie.busyおよびie.ReadyStateは、ie.navigateの直後に有効な回答を返すとは限らないため、ie.navigateの後に少し遅延を導入します。通常は1〜2秒の読み込みですが、500ミリ秒を超えるものはすべて機能するようです。

ターゲットURLに移動する前に、ie.navigate "about:blank"に移動して、IEがクリーンな状態にあることを確認します。

その後、有効なIEオブジェクトが必要になります。そのオブジェクトを調べて、中に何が入っているかを確認する必要があります。通常、私はie.document全体にアクセスしようとするのを避け、代わりにIE.document.all.tags( "x")を使用します。ここで、'x'はtdやaなどの適切なものです。

しかし、これらすべての改善の後、成功率は向上しましたが、それでもランダムにエラーが発生します。

私の本当の解決策は、IEを放棄し、代わりにxmlhttpを使用して作業を行うことでした。

ドキュメントのテキスト操作を使用してデータを解析している場合は、交換するのは簡単です。xmlhttpオブジェクトははるかに信頼性があります。そして、ドキュメントのhtml全体にアクセスするための「responsetext」を取得するだけです。

これは、私が現在本番環境でスクレイピングに使用しているものの簡略化されたバージョンです。非常に信頼性が高く、一晩で実行され、エラーなしで数百万行を生成します。

Public Sub Main()

Dim obj As MSXML2.ServerXMLHTTP
Dim strData As String
Dim errCount As Integer

' create an xmlhttp object - you will need to reference to the MS XML HTTP library, any version will do
' but I'm using Microsoft XML, v6.0 (c:\windows\system32\msxml6.dll)
Set obj = New MSXML2.ServerXMLHTTP

' Get the url - I set the last param to Async=true so that it returns right away then lets me wait in
' code rather than trust it, but on an internal network "false" might be better for you.
obj.Open "GET", "http://www.google.com", True
obj.send ' this line actually does the HTTP GET

' Wait for a completion up to 10 seconds
errCount = 0
While obj.readyState < 4 And errCount < 10
    DoEvents
    obj.waitForResponse 1 ' this is an up-to-one-second delay
    errCount = errCount + 1
Wend

If obj.readyState = 4 Then ' I do these on two
    If obj.Status = 200 Then ' different lines to avoid certain error cases
        strData = obj.responseText
    End If
End If

obj.abort  ' in real code I use some on error resume next, so at this point it is possible I have a failed
           ' get and so best to abort it before I try again

Debug.Print strData

End Sub

お役に立てば幸いです。

于 2012-12-17T07:31:32.840 に答える