2017-12-27 5 views
10

토런트 사이트의 일부 영화 정보를 구문 분석하기 위해 vba에 스크레이퍼를 작성했습니다. 이 작업을 수행하기 위해 IEqueryselector을 사용했습니다. 내 코드를 실행할 때 오류가 발생하면서 모든 것을 구문 분석합니다. 계속하는 대신 오류가 갑자기 나타나지 않는 것 같습니다. 오류 상자를 취소하면 결과를 볼 수 있습니다. 내가 가지고있는 오류를 보여주기 위해 아래에 두 개의 이미지를 업로드했습니다. 오류없이 성공적으로 코드를 실행할 수 있습니까? 미리 감사드립니다.모든 일이 끝나면 내 스크레이퍼에서 브라우저를 종료하는 대신 오류가 발생합니다.

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

모두가 동시에 나타나고있다

여기에 전체 코드입니다. 인터넷 익스플로러 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 프로그램을 실행하는 데 의지했습니다.

따라와 주시기 바랍니다. 로직은 자바 스크립트에 ScriptEngine에 추가되었습니다. 노드 목록 두 개, 영화 목록 하나, 연도 목록 하나를 얻습니다. 그런 다음 각 배열을 동기화하여 단계별로 키 값 쌍으로 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, 위의 스크립트는 라이브러리를 참조하지 않고 실행할 수 있습니다.

관련 문제