2016-10-27 5 views
1

Excel 2013 в Windows 7. XPath/Javascript/jQuery не входит в сферу применения.VBA/DOM - Получить элементы на основе атрибута

Я пытаюсь перебрать элементы div на странице, а именно элементы, которые имеют определенный атрибут data-level.

Мой текущий подход - similar to this, но мне не удалось найти не-ручной способ выбора элементов на основе атрибутов. Ближайший я пришел что-то вроде:

With CreateObject("WINHTTP.WinHTTPRequest.5.1") 
    .Open "GET", url, False 
    .Send 
    pHTML.body.innerHTML = .ResponseText 
End With 

Set eCollection = pHTML.getElementsByClassName("chapter").getElementsByTagName("div") 

For i = 0 To eCollection.Length 
    If eCollection(i).getAttribute("data-level") >= 0 Then ' Throw cake 
Next i 

это решение, в то время как я уверен, что он жизнеспособен (если unelegant), кажется неоптимальным, если только для того, как большой цикл будет в конечном итоге, когда я начинаю ищет конкретные элементы и последовательности элементов в пределах эти элементы.

Так что я искал способ, чтобы сделать что-то вроде этого:

For Each pElement In pHTML.getElementsByClassName("chapter").getElementsByTagName("div").getElementsByAttribute("data-level") 
    ' Throw cake at the element 
Next 

Я знаю, что не существует никакого метода getElementsByAttribute, отсюда вопрос.
Есть ли какой-то подход здесь, что я слепой, или я заблокирован для ручной итерации?

В качестве альтернативы, если поменять мой текущий подход для создания экземпляра IE, а ля this answer, я мог concievably использовать querySelectorAll, чтобы в конечном итоге с чем-то, напоминающим результат я описал выше?

+2

querySelectorAll должен работать, в качестве альтернативы вы можете использовать ExecScript и использовать инструкцию jquery. Что-то вроде этого ответа: http://stackoverflow.com/questions/9032618/find-elements-attribute-value. Я считаю использование jquery чистым способом сделать это, когда мне нужно найти сложный элемент. –

+0

Я не кодирую много JS/jQuery, но я думаю, мне нужно будет узнать, не могу ли я заставить 'querySelector' работать. Спасибо за ввод. – Vegard

ответ

2

Для тех, кто еще идет таким образом, внешнюю оболочку, так сказать, может выглядеть следующим образом:

Sub ScrapeWithHTMLObj(url As String, domClassName As String, domTag As String, domAttribute As String, domAttributeValue As String) 
    ' Dependencies: 
    ' * Microsoft HTML Object Library 

    ' Declare vars 
    Dim pHTML As HTMLDocument 
    Dim pElements As Object, pElement As Object 

    Set pHTML = New HTMLDocument 

    ' Basic URL healthcheck 
    Do While (url = "" Or (Left(url, 7) <> "http://" And Left(url, 8) <> "https://")) 
     MsgBox ("Invalid URL!") 
     url = InputBox("Enter new URL: (0 to terminate)") 
     If url = "0" Then Exit Sub 
    Loop 

    ' Fetch page at URL 
    With CreateObject("WINHTTP.WinHTTPRequest.5.1") 
     .Open "GET", url, False 
     .Send 
     pHTML.body.innerHTML = .ResponseText 
    End With 

    ' Declare page elements 
    Set pElements = pHTML.getElementsByClassName(domClassName) 
    Set pElement = pElements(0).getElementsByTagName(domTag) 

    ' Extract only elements with wanted attribute 
    pEleArray = getElementsByAttribute(pElement, domAttribute, domAttributeValue) 

    For Each e In pEleArray 
     ' Do stuff to elements 
     Debug.Print e.getAttribute(domAttribute) 
    Next 
End Sub 

Если вы идете по этому пути, вы будете также нужно что-то вроде этого:

Function getElementsByAttribute(pObj As Object, domAttribute As String, domAttributeValue As String) As Object() 
    Dim oTemp() As Object 
    ReDim oTemp(1 To 1) 

    For i = 0 To pObj.Length - 1 
     'Debug.Print pObj(i).getAttribute(domAttribute) 
     If pObj(i).getAttribute(domAttribute) = domAttributeValue Then 
      Set oTemp(UBound(oTemp)) = pObj(i) 
      ReDim Preserve oTemp(1 To UBound(oTemp) + 1) 
     End If 
    Next i 

    ReDim Preserve oTemp(1 To UBound(oTemp) - 1) 

    getElementsByAttribute = oTemp 
End Function 

В зависимости от дерева HTML, вам нужно будет изменить, какие элементы, которые вы ноль включаете в sub, очевидно. Для сайта, который я использовал в тестировании, эта структура работала безупречно.

Пример использования:
Call ScrapeWithHTMLObj("https://somesite", "chapter-index", "div", "data-level", "1")

Он войдет в первый класс с именем chapter-index, выбрать все элементы с div тега, и, наконец, извлечь все элементы, содержащие атрибут data-level со значением 1.