Содержимое веб-скрапинга VBA без имени класса или идентификатора

Я хотел бы получить фьючерсные цены на дивиденды с HKEX.

Вот URL-адрес этого сайта: http://www.hkex.com.hk/Market-Data/Futures-and-Options-Prices/Equity-Index/HSCEI-Dividend-Futures?sc_lang=en#&product=DHH

Я хотел очистить расчетную цену Prev.Day по «Контракту 19 декабря» через VBA. Однако у него нет имени класса или идентификатора, поэтому я понятия не имею, как получить доступ к информации.

<tr>
  <td>Dec-19</td>
  <td>-</td>
  <td>-</td>
  <td>413.78</td>
  <td>
    -
    <br>
    -
  </td>
  <td>-</td>
  <td>
    -
    <br>
    -
  </td>
    <td>-<td>
    <td>17,330</td>
  </tr>

Как я могу очистить это через VBA?


person Juuun    schedule 10.11.2017    source источник


Ответы (3)


Это действительно адская автоматизация, чтобы найти конкретный предмет без прикрепленного к нему примечательного флага. Однако я написал этот скрипт без жесткого индексирования элементов. Сделайте это и получите желаемые значения:

Sub Hkex_Data()

    Dim IE As New InternetExplorer, html As HTMLDocument
    Dim posts As Object

    With IE
        .Visible = False
        .navigate "http://www.hkex.com.hk/Market-Data/Futures-and-Options-Prices/Equity-Index/HSCEI-Dividend-Futures?sc_lang=en#&product=DHH"
        Do Until .readyState = READYSTATE_COMPLETE: Loop
        Set html = .document
    End With
    Application.Wait (Now + TimeValue("0:00:05"))

    For Each posts In html.getElementsByClassName("hsirowcon")
        Row = Row + 1: Cells(Row, 1) = posts.NextSibling.NextSibling.FirstChild.innerText
        Cells(Row, 2) = posts.NextSibling.NextSibling.LastChild.innerText
    Next posts

    IE.Quit
End Sub

Результат:

19-Dec  17,330

Ссылка для добавления в библиотеку:

Microsoft internet controls
Microsoft Html Object Library
person SIM    schedule 10.11.2017
comment
Я очистил высший класс и нашел все предметы внутри него. Но ваш код выглядит намного лучше, спасибо. - person Juuun; 13.11.2017

Используйте getElementsByTagName. Определите свой, а затем пройдитесь по каждой строке и каждой тд в строках. Что-то подобное.

Dim objTR As IHTMLElement
Dim objTD As IHTMLElement
Dim objTable As IHTMLElement

For Each objTR In objTable.getElementsByTagName("tr")
    For Each objTD In objTR
        'do something with objtd.innerText
    Next objTD
Next objTR

или вы можете объявить свои переменные как Object, если предпочитаете позднее связывание.

person MarcinSzaleniec    schedule 10.11.2017

Вы также можете просто использовать селектор CSS и не использовать цикл:

html.querySelectorAll("td:nth-child(4)")(1).innerText

Этот метод хрупок. Если стиль на странице изменится, это может сломаться.


Селектор CSS:

Если вы посмотрите на соответствующую часть страницы (показывая первый контрактный год с заголовками для контекста и с удаленной диаграммой между контрактными годами):

Информация о контракте

Связанный HTML-код для контрактного года 2019:

HTML

Prev.Day Settlement Price является четвертым td в этом, т.е. селекторе CSS td:nth-child(4).

Этот шаблон повторяется для всех лет контракта, поэтому вы можете вернуть ему nodeList всех совпадений (т. е. каждые td:nth-child(4) с помощью метода .querySelectorAll).

2019 год находится на индексной позиции 1; это второй элемент в индексированном списке узлов, основанном на 0, поэтому вы получаете доступ с помощью .querySelectorAll("td:nth-child(4)")(1).


Результат запроса CSS – первые несколько результатов:

CSS-запрос

person QHarr    schedule 10.06.2018