2017-12-27 17 views
10

トレントサイトの映画情報を解析するためにvbaにスクレーパーを書きました。私はこの仕事を達成するためにIEqueryselectorを使用しました。私のコードを実行すると、すべてのエラーがポップアップして解析されます。続行するのではなく、どこかでエラーが表示されるようです。エラーボックスをキャンセルすると、結果が表示されます。私は以下の2つの画像をアップロードして、私が過ちているエラーを表示しています。エラーを発生させずにコードを正常に実行するにはどうすればよいですか?前もって感謝します。ここですべてが完了したらブラウザを終了する代わりにスクレーパーがエラーをスローする

は完全なコードです:

Sub Torrent_Data() 
    Dim IE As New InternetExplorer, html As HTMLDocument 
    Dim post As Object 

    With IE 
     .Visible = False 
     .navigate "https://yts.am/browse-movies" 
     Do While .readyState <> READYSTATE_COMPLETE: Loop 
     Set html = .Document 
    End With 

    For Each post In html.querySelectorAll(".browse-movie-bottom") 
     Row = Row + 1: Cells(Row, 1) = post.queryselector(".browse-movie-title").innerText 
     Cells(Row, 2) = post.queryselector(".browse-movie-year").innerText 
    Next post 
    IE.Quit 
End Sub 

私がいるエラー:エラーの

First error

Second error

の両方が同時に登場しています。 私はInternet Explorer 11を使用しています。

一方、私が以下のようにしようとすると、問題は無事に成功します。

Sub Torrent_Data() 
    Dim IE As New InternetExplorer, html As HTMLDocument 
    Dim post As Object 

    With IE 
     .Visible = False 
     .navigate "https://yts.am/browse-movies" 
     Do While .readyState <> READYSTATE_COMPLETE: Loop 
     Set html = .Document 
    End With 

    For Each post In html.getElementsByClassName("browse-movie-bottom") 
     Row = Row + 1: Cells(Row, 1) = post.queryselector(".browse-movie-title").innerText 
     Cells(Row, 2) = post.queryselector(".browse-movie-year").innerText 
    Next post 
    IE.Quit 
End Sub 

私は、ライブラリに追加した参考:だから

1. Microsoft Internet Controls 
2. Microsoft HTML Object Library 

queryselectorまたは何私が正常に行かせるためにここに欠けていると何が間違っていますか?ライブラリをエラーをなくすために追加するリファレンスはありますか?

+0

クイックチェック: 'queryselector'を' querySelector'に変更すると、最初のコードサンプルに違いはありますか? – alecxe

+0

いいえ、全く変更はありません。実際、 'querySelector'を書くと、自動的に' queryselector'という小文字に戻ります。 – SIM

+0

さて、これを試してください: 'post.queryselector'を実行する代わりに' post.innerText'を直接実行してください。あなたがしたいことではありませんが、実験しましょう。あなたは同じエラーを見ますか?ありがとう。 – alecxe

答えて

5

これで、そのウェブページには重大な不公平があります。それは私のためにクラッシュし続けた。だから私はスクリプトエンジン/スクリプト制御の中でjavascriptプログラムを実行することに頼ってきました。

私はあなたがそれに従うことを望みます。ロジックは、JavaScriptでScriptEngineに追加されています。ノードの2つのリスト、1つの映画のリスト、1つの年のリストを取得します。各アレイを同期してステップ実行し、それらをキー値ペアとしてMicrosoft Scripting Dictionaryに追加します。

Option Explicit 

'*Tools->References 
'* Microsoft Scripting Runtime 
'* Microsoft Scripting Control 
'* Microsoft Internet Controls 
'* Microsoft HTML Object Library 

Sub Torrent_Data() 
    Dim row As Long 
    Dim IE As New InternetExplorer, html As HTMLDocument 
    Dim post As Object 

    With IE 
     .Visible = True 
     .navigate "https://yts.am/browse-movies" 
     Do While .readyState <> READYSTATE_COMPLETE: 
      DoEvents 
     Loop 
     Set html = .document 
    End With 

    Dim dicFilms As Scripting.Dictionary 
    Set dicFilms = New Scripting.Dictionary 

    Call GetScriptEngine.Run("getMovies", html, dicFilms) 

    Dim vFilms As Variant 
    vFilms = dicFilms.Keys 

    Dim vYears As Variant 
    vYears = dicFilms.Items 

    Dim lRowLoop As Long 
    For lRowLoop = 0 To dicFilms.Count - 1 

     Cells(lRowLoop + 1, 1) = vFilms(lRowLoop) 
     Cells(lRowLoop + 1, 2) = vYears(lRowLoop) 

    Next lRowLoop 

    Stop 

    IE.Quit 
End Sub 

Private Function GetScriptEngine() As ScriptControl 
    '* see code from this SO Q & A 
    ' https://stackoverflow.com/questions/37711073/in-excel-vba-on-windows-how-to-get-stringified-json-respresentation-instead-of 
    Static soScriptEngine As ScriptControl 
    If soScriptEngine Is Nothing Then 
     Set soScriptEngine = New ScriptControl 
     soScriptEngine.Language = "JScript" 

     soScriptEngine.AddCode "function getMovies(htmlDocument, microsoftDict) { " & _ 
            "var titles = htmlDocument.querySelectorAll('a.browse-movie-title'), i;" & _ 
            "var years = htmlDocument.querySelectorAll('div.browse-movie-year'), j;" & _ 
            "if (years.length === years.length) {" & _ 
            "for (i=0; i< years.length; ++i) {" & _ 
            " var film = titles[i].innerText;" & _ 
            " var year = years[i].innerText;" & _ 
            " microsoftDict.Add(film, year);" & _ 
            "}}}" 

    End If 
    Set GetScriptEngine = soScriptEngine 
End Function 
0

まあ、私は.queryselectorAll()で動作する解決策を見つけたようです。多くの実験を行った結果、for loopにはいくつかの問題があることがわかりましたので、私は触れてもfor loopを避け、同じ仕事をする代わりにwith blockを使用しました。

Sub Torrent_Data() 

    With CreateObject("InternetExplorer.Application") 
     .Visible = False 
     .navigate "https://yts.am/browse-movies" 
     While .Busy = True Or .readyState < 4: DoEvents: Wend 

     With .document.querySelectorAll(".browse-movie-bottom") 
      For I = 0 To .Length - 1 
       Cells(I + 1, 1) = .Item(I).querySelector(".browse-movie-title").innerText 
       Cells(I + 1, 2) = .Item(I).querySelector(".browse-movie-year").innerText 
      Next I 
     End With 
    End With 

End Sub 

Btwこのスクリプトは、ライブラリを参照することなく実行できます。

関連する問題