Как я могу очистить дочерний класс span с помощью VBA?

#html #vba #web-scraping

#HTML #vba #веб-очистка

Вопрос:

Я хотел бы использовать приведенный ниже код, чтобы улучшить позицию в рейтинге в одной из подкатегорий Amazon (конфеты и шоколадные батончики). Пожалуйста, смотрите прикрепленную картинку для получения HTML-кода. Ссылка на «элемент списка» дает мне много результатов, однако «# 204» не является его частью. Таким образом, мой вопрос двоякий: (i) есть ли способ получить все элементы с пометкой «a-list-item» и (ii) есть ли способ, который просто возвращает мне позицию в рейтинге, не вытаскивая все остальные элементы. Вариант (ii) был бы лучше для моих целей.

Спасибо за ваше время и усилия.

html-код с целевым значением

 Public Sub social()
     
'--------------------------------------------------------------------------
   
    Dim WSactive As Worksheet
    Dim IE As New InternetExplorer

    Set WBactive = ActiveWorkbook
    Set WSactive = WBactive.Sheets("Tabelle1")
    
'-----------------------------------------------------------------------------

    On Error Resume Next

'-------------------------------------------------------------------------

    With WSactive
        Dim results(0 To 4) ', counter As Long, i As Long
        With IE
            .Visible = False
            
                'If TBLurl.DataBodyRange.Cells(i, w).Value <> "" Then
                    url = "https://www.amazon.com/dp/B08X19ZCHS?ref=myi_title_dp"
                    .navigate url

'--------------------------------------------------------------------------

                    While .Busy Or .readyState < 4: DoEvents: Wend
                    Dim aNodeList As Object, ele As Object, t As Date
                    Const MAX_WAIT_SEC As Long = 5
                    t = Timer

                    Do
                        DoEvents
                        On Error Resume Next
                        Set ele = .document.querySelector(".rhpdm")
                        On Error GoTo 0
                        If Timer - t > MAX_WAIT_SEC Then Exit Do
                    Loop While ele Is Nothing

'--------------------------------------------------------------------------
                    
                    Set aNodeList = .document.querySelectorAll(".a-list-item")
                    Dim j As Long
                    For j = 0 To aNodeList.Length - 1
                       Debug.Print aNodeList.Item(j).innerText
                    Next j
                    Set aNodeList = Nothing: Set ele = Nothing
            .Quit 'close IE
        End With

    End With

'-------------------------------------------------------------------------

End Sub
 

Комментарии:

1. Используйте библиотеку с открытым исходным кодом, которая поддерживается множеством разработчиков, вместо того, чтобы пытаться создавать свои собственные по одному вопросу за раз в StackOverflow: github.com/VBA-tools/VBA-Web

Ответ №1:

Отображается только 1 URL-адрес, и путь css к этому узлу может быть

 Debug.Print .document.querySelector('#detailBulletsWrapper_feature_div #detailBullets_feature_div   ul .a-list-item .a-list-item').innerText
 

— это смежный комбинатор, определяющий ul, который следует на том же уровне за элементом с идентификатором detailBullets_feature_div. Пробелы являются комбинаторами-потомками, то есть элементы справа являются дочерними элементами элементов слева от пробела. Тот самый . являются селекторами классов для имен классов элементов.

Однако HTML-код в вашем изображении, по-видимому, немного отличается от предоставленного URL-адреса. Ваш пробег при использовании вышеуказанного решения может варьироваться. Я пошел на позиционное сопоставление, исходя из предположения, что другие страницы будут иметь аналогичный макет.

Даже если бы вы выполняли цикл по разным страницам, страницы в соответствии с предоставленным URL-адресом имели бы только один рейтинг (если так, как показано на вашем изображении).


Вам не нужны накладные расходы браузера. Ниже показано, как получить оба рейтинга на странице (а не только тот, который вы показали) с помощью xhr:

 Option Explicit
Public Sub PrintRankings()
    'tools > references > Microsoft HTML Object Library
    Dim html As MSHTML.HTMLDocument, xhr As Object
    
    Set xhr = CreateObject("MSXML2.XMLHTTP")
    Set html = New MSHTML.HTMLDocument

    With xhr
        .Open "GET", "https://www.amazon.com/dp/B07YG6MTD3?ref=myi_title_dpamp;th=1", False
        .setRequestHeader "User-Agent", "Mozilla/5.0"
        .send
        html.body.innerHTML = .responseText
    End With

   Debug.Print html.querySelector("#detailBullets_feature_div   ul span > span").NextSibling.NodeValue
   Debug.Print html.querySelector("#detailBulletsWrapper_feature_div #detailBullets_feature_div   ul .a-list-item .a-list-item").innerText
    
End Sub
 

Комментарии:

1. спасибо как за рабочий код, так и за справочную информацию. очень признателен.

2. Я очарован этим скорректированным кодом: он намного компактнее моего. однако есть два вопроса: (1) откуда вы знаете, что «detailBulletsWrapper_feature_div» — это раздел, с которого нужно начать? (2) есть ли документация, которую я могу прочитать по всему этому?

3. Я использую Debug.Print html.querySelector("#productDetails_db_sections #productDetails_detailBullets_sections1 tr tr tr .td").innerText для извлечения рейтинга со страницы ниже, пытаясь скопировать ваш код. Что я здесь делаю не так?

4. Вот ссылка: ссылка

5. Спасибо, что поделились этими ссылками. Первый помог мне настроить мой код с помощью ~ (general sibling combinator). Затем мой код выглядит следующим образом: Debug.Print html.querySelector("#productDetails_db_sections tr tr tr span > span").innerText '>> gives back overall rank in grocery Debug.Print html.querySelector("#productDetails_db_sections tr tr tr span > span ~ span").innerText '>> gives back rank in candies