2016-08-12 5 views
1

다시 한 번 매우 구체적인 문제가 발생했습니다. 나는 VBA, 특히 HTML에 익숙하기 때문에 나와 함께 감당해야한다. 나는 VBA에서 작동하는 웹 스크레이퍼를 만들었지 만 내가 알아낼 수없는 몇 가지 구체적인 작업이 있습니다.VBA에서 특정 부모 HTML 요소의 자식에서 데이터를 가져 오는 방법

Here is the HTML sample that my question refers to.

나는 타원으로 문제가되지 않는 모든 재료를 교체했습니다. 내가 긁어 내고 싶은 중요한 부분은 "a"태그 인 "data-shorturl"(또는 단지 innerText)입니다. 이것은 웹 사이트 이름입니다. 이 중 최대 5 개가 있지만 항상 5 개가있는 것은 아닙니다. 이것은 최대 5 개의 웹 사이트가 나열된 두 섹션 중 하나 일뿐입니다. 게시 된 섹션의 자식은 <div class="referralsSites referring">이고 다른 자식은 <div class="referralsSites destination">입니다.

"추천"섹션의 각 웹 사이트 "Up"변수에 할당하려는 첫 번째 웹 사이트 - "Up1"에 할당 된 첫 번째 웹 사이트, 두 번째 "Up2"등에 할당되는 웹 사이트 수 : 얼마나 많은 웹 사이트 "추천"부분에 있습니다. "대상"섹션에서 동일한 작업을 수행하려고하지만 대상 사이트 수에 따라 "아래로"변수 (Down1, Down2 등)에 할당됩니다.

예를 들어 getElementsByClassName("websitePage-listItemLink js-tooltipTarget")을 사용한다면 참조 사이트와 대상 사이트를 구분할 수 없습니다. 나는이 문제를 접근하는 방법을 정말 잘 모르겠어요

Sub GetSimilarWebData() 
    Dim appIE As InternetExplorer 
    Dim HTML As HTMLDocument 
    Dim ieWindow As SHDocVw.InternetExplorer 
    Dim URL As String 
    Dim Rankings As IHTMLElementCollection, Traffic As IHTMLElementCollection, ReferSites As IHTMLElementCollection, DestSites As IHTMLElementCollection, _ 
     rSite As IHTMLElement, rSiteNo As Long, dSite As IHTMLElement, dSiteNo As Long, GlobalRank As String, CountryName As String, CountryRank As String, _ 
     Visits As String, Direct As String, Refer As String, Search As String, Social As String, Display As String, _ 
     Up1 As String, Up2 As String, Up3 As String, Up4 As String, Up5 As String, _ 
     D1 As String, D2 As String, D3 As String, D4 As String, D5 As String 
    Dim FraudLast As Long 
    CheckLast = Worksheets("Sheet1").Range("I1").End(xlDown).Offset(1).Row 

    webStr = Worksheets("Sheet1").Range("A" & CheckLast).Value 

    Set appIE = New InternetExplorer 
     appIE.Visible = False 
     appIE.navigate "https://www.similarweb.com/website/" & webStr 

    Do While appIE.readyState <> READYSTATE_COMPLETE 
     Application.StatusBar = "Connecting to SimilarWeb..." 
     DoEvents 
    Loop 

    Set HTML = appIE.document 

    Set appIE = Nothing 
     Application.StatusBar = "" 

    Set Rankings = HTML.getElementsByClassName("rankingItem-value") 
     GlobalRank = Rankings(0).innerText 
      If GlobalRank = "N/A" Then 
       GlobalRank = "null" 
       CountryName = "null" 
       CountryRank = "null" 
      Else 
       CountryName = HTML.getElementsByClassName("rankingItem-subTitle")(1).innerText 
       CountryRank = Rankings(1).innerText 
      End If 

    Visits = HTML.getElementsByClassName("engagementInfo-value engagementInfo-value--large u-text-ellipsis")(0).innerText 
     If InStr(Visits, "M") <> 0 Then 
      Visits = Replace(Visits, ".", "") 
      Visits = Replace(Visits, "M", "00000") 
     ElseIf InStr(Visits, "K") <> 0 Then 
      Visits = Replace(Visits, ".", "") 
      Visits = Replace(Visits, "K", "00") 
     ElseIf InStr(Visits, "B") <> 0 Then 
      Visits = Replace(Visits, ".", "") 
      Visits = Replace(Visits, "B", "00000000") 
     End If 

    Set Traffic = HTML.getElementsByClassName("trafficSourcesChart-value") 
     Direct = Traffic(0).innerText 
     Refer = Traffic(1).innerText 
     Search = Traffic(2).innerText 
     Social = Traffic(3).innerText 
     Display = Traffic(4).innerText 

'Here's what I've started off with:  
    Set ReferSite = HTML.getElementsByClassName("referralsSites referring") 
     rSiteNo = ReferSite.Length 
    Set DestSite = HTML.getElementsByClassName("referralsSites destination") 
     dSiteNo = DestSite.Length 
     'For Each rSite In ReferSite 
End Sub 

:

여기에 지금까지 내 코드입니다. 내 코드의 다른 모든 것은 잘 작동하지만, 속도를 향상시키기 위해 할 수있는 일이 있다면 환영받을 것입니다.

이 모든 것은 similarweb.com의 데이터를 참조합니다.

답변

1

getElementsByClassName 방법은 IHTMLElement 개체 및 HTMLDocument 개체에서 사용될 수 있습니다. 즉, 추천 및 대상 사이트 목록을 두 번씩 '홉'으로 가져올 수 있습니다.

먼저 또는 referralsSites destination의 클래스 이름을 사용하여 <div>을 가져옵니다. getElementsByClassName 메서드는 IHTMLElement의 컬렉션 인 IHTMLElementCollection을 반환합니다. 따라서 컬렉션의 0 번째 요소 (<div> 만 있다고 가정)를 가져온 다음 <div>의 에 getElementsByClassName 메서드를 다시 호출하여 websitePage-listItemLink 클래스의 <div> 안에 <a>을 가져옵니다.

다음은 stackoverflow.com의 예제입니다. 출력의 Debug.Print을 수행하고 있지만 사이트 이름을 배열 또는 Collection 또는 무언가로 지정하려고 할 수 있습니다.

Option Explicit 

Sub Test() 

    'references required: 
    'Microsoft HTML Object Library 
    'Microsoft Internet Controls 

    Dim strUrl As String 
    Dim objIe As InternetExplorer 
    Dim objHtml As HTMLDocument 
    Dim strHtml As String 
    Dim objDivs As IHTMLElementCollection 
    Dim objAnchors As IHTMLElementCollection 
    Dim intCounter As Integer 

    'set target to scrape 
    strUrl = "https://www.similarweb.com/website/stackoverflow.com" 

    'get html from page 
    Set objIe = New InternetExplorer 
    objIe.Visible = False 
    objIe.navigate strUrl 
    While objIe.readyState <> READYSTATE_COMPLETE 
     DoEvents 
    Wend 

    'assign html to DOM document 
    Set objHtml = New HTMLDocument 
    Set objHtml = objIe.document 

    'get referrals 
    Set objDivs = objHtml.getElementsByClassName("referralsSites referring") 
    If objDivs.Length > 0 Then 
     Set objAnchors = objDivs(0).getElementsByClassName("websitePage-listItemLink") 
     Debug.Print "Referrers:" 
     If objAnchors.Length > 0 Then 
      For intCounter = 0 To objAnchors.Length - 1 
       Debug.Print objAnchors(intCounter).innerText 
      Next intCounter 
     End If 
    End If 

    'get destinations 
    Set objDivs = objHtml.getElementsByClassName("referralsSites destination") 
    If objDivs.Length > 0 Then 
     Set objAnchors = objDivs(0).getElementsByClassName("websitePage-listItemLink") 
     Debug.Print "Destinations:" 
     If objAnchors.Length > 0 Then 
      For intCounter = 0 To objAnchors.Length - 1 
       Debug.Print objAnchors(intCounter).innerText 
      Next intCounter 
     End If 
    End If 

    'clean up 
    Set objHtml = Nothing 
    objIe.Quit 
    Set objIe = Nothing 

End Sub 

이의 출력을 제공합니다

Referrers: 
news.ycombinator.com 
qwant.com 
github.com 
remoteok.io 
serverfault.com 
Destinations: 
jsfiddle.net 
youtube.com 
github.com 
i.stack.imgur.com 
w3schools.com 
+0

가 감사를! 이것은 내가 찾고 있었던 바로 그 것이다. 나는'getElementsByClassName()'이 자식 요소에도 접근 할 수 있다는 것을 몰랐다. – TradorDave

관련 문제