Одна из приятных и сложных вещей, связанных с просмотром веб-страниц, заключается в том, что, как правило, каждый сайт отличается, и часто страницы, принадлежащие одному и тому же сайту, могут отличаться. Я понимаю, что у вас есть только небольшой опыт, поэтому я боюсь, что следующее - это немного кривой обучения. Сценарий для вашего другого ответа был довольно простым в тех столбцах в табличном формате, где циклически повторяются строки.
Переносимая часть всего этого - это изучение того, как читать HTML, и принятие решения, когда использовать XMLHTTP (который я использую ниже и является более быстрым методом извлечения, но не будет извлекать все со страницы - особенно если страница имеет большой объем JavaScript) по сравнению с решением на основе браузера. Потренируйтесь в использовании инструментов инспекции / разработки, чтобы поиграть с выбором информации.
Тогда есть общие биты кода, которые вы обычно будете использовать каждый раз, например, при использовании IE у вас почти всегда будут одни и те же строки соединения кода и строки ожидания кода. С xmlHttp вы, как правило, также будете повторно использовать вводные строки кода. Но, поскольку веб-сайты, как правило, довольно разные, вам нужно будет изучить, как анализировать DOM
каждый раз, чтобы получить нужную информацию. Со страницами, принадлежащими одному и тому же сайту / хосту, вы можете повторно использовать больше кода, если их разработчики последовательны в дизайне своих страниц. Только не ожидайте, что это так.
В приведенном ниже сценарии используется querySelectorAll , в данном случае метод HTMLDocument , для первоначальной генерации nodeLists
путем сопоставления элементов по их именам классов .
Эти строки ниже генерируют то, что вы можете считать списками. Каждый элемент в списке имеет одинаковое имя класса.
Set teamsVisitors = .querySelectorAll(".lineup__team.is-visit")
Set teamsHomies = .querySelectorAll(".lineup__team.is-home")
Set nickNamesVisitors = .querySelectorAll(".lineup__mteam.is-visit")
Set nickNamesHomies = .querySelectorAll(".lineup__mteam.is-home")
Set visitors = .querySelectorAll(".lineup__list.is-visit") ' then by li
Set homies = .querySelectorAll(".lineup__list.is-home") ' then by li
Итак, давайте посмотрим на один из этих списков. nodeList
, связанный с
Set teamsVisitors = .querySelectorAll(".lineup__team.is-visit")
![image](https://i.stack.imgur.com/rfKPv.png)
Вы можете видеть, как это собрало 4 буквы из двух букв в команде nodeList
(вы могли бы подумать о коллекции, но вы не можете For Each
над ней, и на самом деле это больше похоже на массив).
Я дал переменным достаточно описательные имена, чтобы вы знали, что находится в каждом списке, но если вы не уверены, вы можете перейти к инструментам разработчика (F12 в Chrome, FireFox), выделить любой бит HTML на вкладке элементов а затем Ctrl + F , чтобы вызвать окно поиска HTML и ввести текст между ""
из querySelectorAll
в это поле, например .lineup__team.is-visit
![image](https://i.stack.imgur.com/fcGHo.png)
Вы видите, что он возвращает количество совпадений в HTML для селектора CSS. Вы можете использовать ввод для их циклического перемещения.
Итак, у меня есть серия nodeList
с. Каждый индекс, например Индекс 0
, в каждом nodeList
, относится к одному совпадению. Итак, по индексу 0
у меня есть GS v BKN i.e. Warriors v Nets
.
Я зацикливаю nodeList
s, записывая информацию о совпадении на лист. Чтобы получить подтвержденную информацию об игроке, мне нужно еще поделить nodeList
s на:
Set visitors = .querySelectorAll(".lineup__list.is-visit") ' then by li
Set homies = .querySelectorAll(".lineup__list.is-home") ' then by li
Взять индекс 0
в visitors nodeList
у нас есть:
![image](https://i.stack.imgur.com/aP88S.png)
Нам нужна дополнительная информация; простого использования имени класса было недостаточно. Если мы посмотрим на HTML, то увидим, что на самом деле отдельные элементы разделены на li
элементов тега списка:
Это означает, что мы можем использовать метод .getElementsByTagName
для возврата этих элементов. Например:
homies.item(i).getElementsByTagName("li")
В итоге это выглядит так (пример):
![image](https://i.stack.imgur.com/0Dqgo.png)
В моем цикле я записываю посетителей в левую колонку, а домой справа. Когда я перебираю индексы (то есть каждое совпадение) в исходных nodeList
s, я добавляю +3
к номеру выходного столбца, чтобы вы получили разнесенную запись для каждой таблицы.
Пример вывода:
![enter image description here](https://i.stack.imgur.com/bIjgF.png)
VBA:
Option Explicit
Public Sub GetMatchInfo()
Dim sResponse As String, html As HTMLDocument
Application.ScreenUpdating = False
With CreateObject("MSXML2.XMLHTTP")
.Open "GET", "https://www.rotowire.com/basketball/nba-lineups.php", False
.setRequestHeader "If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT"
.send
sResponse = StrConv(.responseBody, vbUnicode)
End With
Set html = New HTMLDocument
Dim visitors As Object, teamsVisitors As Object, nickNamesVisitors As Object
Dim homies As Object, teamsHomies As Object, nickNamesHomies As Object
Dim i As Long, r As Long, c As Long, j As Long
With html
.body.innerHTML = sResponse
Set teamsVisitors = .querySelectorAll(".lineup__team.is-visit")
Set teamsHomies = .querySelectorAll(".lineup__team.is-home")
Set nickNamesVisitors = .querySelectorAll(".lineup__mteam.is-visit")
Set nickNamesHomies = .querySelectorAll(".lineup__mteam.is-home")
Set visitors = .querySelectorAll(".lineup__list.is-visit") ' then by li
Set homies = .querySelectorAll(".lineup__list.is-home") ' then by li
End With
With ThisWorkbook.Worksheets("Sheet1")
r = 1: c = 1
For i = 0 To teamsHomies.Length - 1
.Cells(r, c) = teamsVisitors.item(i).innerText
.Cells(r, c + 1) = teamsHomies.item(i).innerText
r = r + 1
.Cells(r, c) = nickNamesVisitors.item(i).innerText
.Cells(r, c + 1) = nickNamesHomies.item(i).innerText
Dim numHomiesLiElements As Long, numVisitorsLiElements As Long, maxNumberofLiElements As Long
numHomiesLiElements = homies.item(i).getElementsByTagName("li").Length - 1
numVisitorsLiElements = visitors.item(i).getElementsByTagName("li").Length - 1
maxNumberofLiElements = IIf(numHomiesLiElements > numVisitorsLiElements, numHomiesLiElements, numVisitorsLiElements)
For j = 0 To maxNumberofLiElements
r = r + 1
On Error Resume Next
.Cells(r, c) = visitors.item(i).getElementsByTagName("li")(j).innerText
.Cells(r, c + 1) = homies.item(i).getElementsByTagName("li")(j).innerText
On Error GoTo 0
Next
r = 1: c = c + 3
Next
End With
Application.ScreenUpdating = True
End Sub
Ссылки (VBE> Инструменты> Ссылки):
- Библиотека объектов Microsoft HTML
Ресурсы, которые могут вам помочь:
- getElementsByTagName
- Селекторы классов CSS
- XMLHTTP-запросы
Смотрите здесь для улучшенного сценария на основе Python:
https://stackoverflow.com/a/55626217/6241235