#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