Извлечение данных веб-страницы из скрытого меню, которое открывается после нажатия - PullRequest
2 голосов
/ 10 марта 2020

Новичок в VBA и круги, пытающиеся извлечь данные из таблицы на веб-странице, которая появляется только после ее нажатия.

Я использую макрос VBA в Excel для извлечения данных из погоды. com:

  1. Я могу успешно извлечь элементы из видимой таблицы.
  2. Я вытаскиваю ошибку 91 при попытке извлечь время «восхода» и «заката» из скрытого меню .
  3. Я бы хотел извлечь время восхода и захода солнца со 2-го дня на столе.

Вопрос:

  1. Есть ли способ щелкнуть внутри кода, чтобы показать данные, которые я хочу извлечь?
  2. Эти данные находятся в пределах SPAN в исходном коде. Можно ли извлечь этот innerText из ближайшего ClassName в SPAN в вопросе?

Кто-нибудь возражал бы взглянуть на код и помочь мне? Спасибо!

Я могу успешно извлечь "день", "погода" и "темп", но не могу вытащить "srise".

Вот мой код VBA:

Sub Get_Lancaster()
Dim request As Object
Dim response As String
Dim html As New HTMLDocument
Dim website As String
Dim weather As Variant
Dim temp As Variant
Dim day As Variant
Dim srise As Variant

website = "https://weather.com/weather/5day/l/2db548c2f0fb03c25c0d5c5520a32877082d295d907b06df5eff91cd140165b9"

Set request = CreateObject("MSXML2.XMLHTTP")

request.Open "GET", website, False

request.setRequestHeader "If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT"

request.send

response = StrConv(request.responseBody, vbUnicode)

html.body.innerHTML = response

weather = html.getElementsByClassName("description").Item(2).innerText
temp = html.getElementsByClassName("temp").Item(2).innerText
day = html.getElementsByClassName("day-detail clearfix").Item(1).innerText
srise = html.getElementsByClassName("sunrise").Item(1).innerText

Range("B3").Value = day
Range("D3").Value = weather
Range("E3").Value = temp
Range("G3").Value = srise

End Sub

Вот код источника HTML для меню после того, как оно щелкнуло и открылось на исходной странице:

Я пытаюсь извлечь 7:05 утра, расположенный в нижней части SPAN:

<tr classname="clickable open" class="clickable open">
<td class="twc-sticky-col cell-hide">
    <div classname="twc-table-shadow sticky" class="twc-table-shadow sticky"></div>
  </td>

<td headers="uv-index" title="Partly cloudy skies. High around 40F. Winds light and variable." data-track-string="ls_24_hour_ls_24_hour_toggle" classname="uv" class="uv">
    <span class="">3 of 10</span>
  </td>

<td headers="sunrise" title="Partly cloudy skies. High around 40F. Winds light and variable." data-track-string="ls_24_hour_ls_24_hour_toggle" classname="sunrise" class="sunrise">
  <div>
    <span classname="icon icon-font iconset-astro dark icon-sunrise" class="icon icon-font iconset-astro dark icon-sunrise">
    </span>
    <span>7:05 am</span>
  </div>
</td>

Спасибо, что взглянули и помогли новичку ie, который над их головой!

-J

1 Ответ

1 голос
/ 11 марта 2020

Вы хорошо поработали, +1 за усилия, которые вы приложили в этом!

Я бы хотел сделать еще один шаг, если вы не возражаете.

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

Действительно, в этом случае, если вы на самом деле щелкните правой кнопкой мыши и просмотрите исходный код страницы, вы не найдете размещенный вами фрагмент HTML. Однако вы найдете его, если осмотрите интересующий элемент.

Это происходит потому, что эта часть кода HTML создается сценарием. Вы найдете этот скрипт в исходном коде страницы внутри тега <script></script> (например, просто ищите "sunrise"). Этот тег содержит огромную строку и вторую маленькую строку в формате JSON.

Тег script выглядит следующим образом:

<script charSet="UTF-8">window.__data={"transactionId":"a3520089-63d0-4320-bb6e-c6308b6e820d", ... {"startIndex":0}};window.experience={"connectionSpeed":"4g","deviceClass":"desktop"};</script>

I Для удобства чтения заменили большую часть строки на ....

Все необходимые данные находятся в первой строке JSON (window.__data) между фигурными скобками {...}. Вам не понадобится вторая строка (window.experience).

Поэтому в основном вам нужно изолировать эту строку от ответа и затем проанализировать ее, чтобы получить необходимую информацию.

Вы можете проверить структуру строки JSON, используя такой инструмент, как this . Вот как это выглядит:

enter image description here

Чтобы разобрать строку, подобную этой, вам нужно добавить this JSON parser в ваш проект. Следуйте инструкциям по установке, приведенным в ссылке, и вы должны установить go.

. Вам также необходимо добавить следующие ссылки на ваш проект (VBE> Инструменты> Ссылки):

Microsoft XML version 6.0
Microsoft Scripting Runtime

Сказав это, вот как я это сделаю:

Option Explicit

Sub weather()
Dim req As New MSXML2.XMLHTTP60
Dim url As String, data As String, startOfData As String, endOfData As String
Dim dataJSON As Object, day As Object

startOfData = "window.__data=" 'the string of interest starts after this
endOfData = ";window.experience=" 'the string of interest ends before this

url = "https://weather.com/weather/5day/l/2db548c2f0fb03c25c0d5c5520a32877082d295d907b06df5eff91cd140165b9"
With req
    .Open "GET", url, False
    .send
    data = .responseText
End With

data = Mid(data, InStr(1, data, startOfData) + Len(startOfData)) 'isolate the string of interest: step 1
data = Mid(data, 1, InStr(1, data, endOfData) - 1) 'isolate the string of interest: step 2

Set dataJSON = JsonConverter.ParseJson(data)
Set dataJSON = dataJSON("dal")("DailyForecast")("geocode:44.49,-71.57:language:en-US:units:e")("data")("vt1dailyForecast")

For Each day In dataJSON
    Debug.Print day("sunrise")
    Debug.Print day("day")("narrative")
    Debug.Print day("night")("narrative")
Next day

End Sub

В демонстрационных целях вышеприведенный код печатает только восход и рассказ каждого дня в ближайшем окне. Имея в виду структуру JSON и следуя той же логике c, вы можете настроить код для печати того параметра, который вам нужен.

Вот пример вывода:

enter image description here

...