4

レンダリング Web サイトの特定のフィールド/ラベルを Web スクレイピングするスクリプトを作成しようとしています。Web サイトは、Excel の列リストにある検索パラメーターを使用してレンダリングされます。成長する約20アイテム。vbscripts を Web スクレイプに使用する方法を調査した後、私が直面している問題は、これを 20 回実行しても壊れないということです。これが私のコードです。

エクセル列

1492565
1528417
1529041
1530688
1492038
1492319
1492972
1508824
1513351
1514724
1514750
1518526
1520627
1520706
1520979
1523367
1523563

スクリプト: メイン サブ (Excel の入力フィールドからユーザー/パスを取得し、特定の列の行を介してループを設定します。ループが機能するようになるまで、msgbox のみを吐き出します。次に、それを別の列に出力します。

Sub WebScraper()
    'itg on mainWS start row 6, column 5
    'itg status column column 19
    'declare variables
    Dim url As String
    Dim ITGNUMBER As Long
    Dim user As String
    Dim pwd As String
    
    'set variables
    url = "https://website/itg/web/knta/crt/RequestDetail.jsp?REQUEST_ID="
    Set oMainWS = ActiveWorkbook.Worksheets("MainWS")
    Set oITGStatusWS = ActiveWorkbook.Worksheets("ITGStatus")
    user = ""
    pwd = ""
    
    user = oITGStatusWS.ITGusername.Value
    pwd = oITGStatusWS.ITGpassword.Value
    
    If user = "" Or pwd = "" Then
        MsgBox ("You must enter username/password before continuing")
        Exit Sub
    End If
    
    'log in
    Set objIE = FirstIEConnect(user, pwd)
    
    'start row is 6
    RowCounter = 58
    ColumnCounter = 5
    ITGStatusColumn = 16
    Do Until IsEmpty(oMainWS.Cells(RowCounter, 5).Value)
        'get ITG number
        currentITGNumber = oMainWS.Cells(RowCounter, 5).Value
        MsgBox (currentITGNumber)
        'get remote status
        currentITGStatus = getITGStatusFunction(objIE.Application, Str(currentITGNumber))
        MsgBox (currentITGStatus)
        
        'paste into column 19
        'oMainWS.Cells(RowCounter, 19).Value = currentITGStatus
        
        'increment counter
        RowCounter = RowCounter + 1
        currentITGStatus = ""
        currentITGNumber = ""
    Loop
    quitIE (objIE.Application)
End Sub

サブにはquitIEオブジェクトのクリーニングがあり、ユーザーをログアウトするJavaScript関数があります。

Sub quitIE(obj As Object)
    obj.Navigate ("javascript: closeChildWindowsAndLogout();")
    obj.Quit
End Sub

Google からこのサブを取得し、IE オブジェクトの準備が整うまで待機していました。これは実際にはループで多く失敗します。On Do While IE.Busy:Loop。ただハングします。

Sub Wait(obj As Object)
    Do While obj.Busy: Loop
    Do While obj.readyState <> 4:   Loop
     Application.Wait (Now + TimeValue("0:00:01"))
End Sub

Web サイトにはログオンが必要です。user/pwd は最初のサブからのものです。Document.logon.UserNameこのサブルーチンは、IE オブジェクトを作成し、ログオン ページに移動して、user/pwd をandに挿入しますDocument.logon.Password。最後に提出します。

Function FirstIEConnect(user As String, pwd As String)
    loginURL = "https://website/Logon.jsp"
    Set IE = CreateObject("InternetExplorer.Application")
    IE.Visible = False
    IE.Navigate loginURL
    Wait (IE.Application)
    With IE.Document.logon
      .UserName.Value = user
      .Password.Value = pwd
      .submit
    End With

    Set FirstIEConnect = IE
End Function

これが実際の Web スクレイピング機能です。ユーザーは上から IE オブジェクトにログインする必要があります。num を url GET リクエストに入力して、特定のページをレンダリングします。最後responseTextに ElementID に基づいて取得します

Function getITGStatusFunction(obj, num)
    On Error Resume Next
    'set url and num
    url = "https://website/RequestDetail.jsp?REQUEST_ID=" & num
  
    obj.Navigate url
    Wait (obj.Application)
    responseText = obj.Document.getElementByID("DRIVEN_STATUS_ID").innerHTML
   
    getStatusFunction = responseText
    
End Function

繰り返しますが、問題は、さまざまなサブルーチンや関数から IE オブジェクトを渡そうとすると、オブジェクト エラーが発生し続けることです。

期待: スクリプトで、一意の番号を含む Excel の列情報をループ処理する必要があります。これらの番号を 1 つずつ取得し、検索 URL に 1 つずつ追加します。ページが読み込まれたら、ElementID(DRIVEN_STATUS_ID). 最終的にその値を取得して別の列に出力します。

4

3 に答える 3

1

暗闇の中でのショットですが、値を設定しようとしたときに HTML が完全に読み込まれていないように聞こえます。待機値を長くしてみてください。通常、3 ~ 4 秒でうまくいきます。

または、新しい変数を作成して、オブジェクトが設定されるまでループを設定することもできます。

Dim obj_testVariable as Object

Do Until Not obj_testVariable Is Nothing
   set obj_testVariable = obj.Document.getElementByID("DRIVEN_STATUS_ID")
Loop

responseText = obj_testVariable.innerHTML

set obj_testVariable = Nothing

(未テスト)

于 2012-09-01T22:17:56.833 に答える
1

Wait (IE)IE.Nameオブジェクトの代わりに渡されます。オブジェクトを渡すには、 を使用しますIE.Application

Tim Williams のコメントも正しいです。括弧を省略すると、オブジェクトが渡されます。そのためWait IE、代わりにWait (IE)動作します。Wait IE.Applicationしかし、明示的に使用する方が安全だと思います。明らかに、あなたが決めます。

待機関数を更新しても問題は解決しませんが、問題の場所がより明確になります。 Function Wait(IE as object)オブジェクトが必要であることを示す関数を呼び出そうとすると失敗します。

これはこの時点で明らかなはずですが、実際にオブジェクトの名前だけが必要な場合を除き、すべてのインスタンスIEを渡さないでください。IE.Application

余談Set variable = IEですが、キーワードSetによってオブジェクトが必要であることが明確になるため、線は問題ありません。

于 2012-08-31T16:05:34.907 に答える