tl; dr
Ваша ошибка связана с тем, что для данного имени класса имеется разное количество элементов в зависимости от результатов на странице.Таким образом, вы не можете использовать фиксированные индексы.Для страницы, которую вы указали, последний индекс для этого класса через iframe равен 9, т.е. ThisWorkbook.Worksheets("Sheet1").cells(u, 9) = .getElementsByClassName("formContentData")(9).innerText
.10 и 11 недействительны.Ниже я показываю способ определения количества результатов и извлечения информации из каждой строки результатов.
Общий принцип:
Хорошо ... так что следующее работает надпринцип нацеливания на таблицу Details of Changes
для большей части информации.
Пример извлечения:

Более конкретно, я нацеливаюсь на строки, которые повторяют информацию для No, Date of Change, #Securities, Type of Transaction and Nature of Interest
.Эти значения хранятся в массиве массивов (один массив на строку информации).Затем массивы результатов сохраняются в коллекции для последующей записи на лист.Я заполняю каждую ячейку таблицы в целевых строках (td
элементы тега в родительском tr
), чтобы заполнить массивы.
Я добавляю Name
из таблицы выше на странице, а также, потому чтов зависимости от веб-страницы может быть несколько строк результатов, и поскольку я записываю результаты на новый лист Results
, я добавляю URL
перед каждым результатом, чтобы указать источник информации.
TODO:
- Изменить код на более модульный
- Потенциально добавить в некоторую обработку ошибок
CSS селекторы:
select Я выбираю элемент Name
, который я называю title
, из таблицы Particulars of substantial Securities Holder
.
ПримерЭлемент name:
Проверка HTML для этого элемента показывает, что он имеет класс formContentLabel
, ичто это первый класс с этим значением на странице.
Пример HTML-кода для целевого имени:
Это означает, что я могу использовать селектор класса , .formContentLabel
, для нацеливания на элемент.Поскольку это единственный элемент, я хочу использовать метод querySelector
для применения селектора CSS.
target Я нацеливаю интересующие строки в таблице Details of Changes
с помощью комбинации селекторов .ven_table tr
.Это комбинация потомок , объединяющая элементы выбора с тегом tr
, имеющим родителя с классом ven_table
.Поскольку это несколько элементов, я использую метод querySelectorAll
, чтобы применить комбинацию селекторов CSS.
Пример целевой строки:
Пример результатов, возвращаемых селектором CSS (образец):

Интересующие меня строки начинаются с 1 и повторяются каждые + 4 строки, например, после строк 5, 9 и т. Д. Поэтому я использую небольшую математику в коде, чтобы вернуть только интересующие строки:
Set currentRow = data.item(i * 4 + 1)
VBA:
Option Explicit
Public Sub GetInfo()
Dim IE As New InternetExplorer, headers(), u As Long, resultCollection As Collection
headers = Array("URL", "Name", "No", "Date of change", "# Securities", "Type of Transaction", "Nature of Interest")
Set resultCollection = New Collection
Dim links()
links = Application.Transpose(ThisWorkbook.Worksheets("Sheet1").Range("A2:A3")) 'A100
With IE
.Visible = True
For u = LBound(links) To UBound(links)
If InStr(links(u), "http") > 0 Then
.navigate links(u)
While .Busy Or .readyState < 4: DoEvents: Wend
Application.Wait Now + TimeSerial(0, 0, 1) '<you may not always need this. Or may need to increase.
Dim data As Object, title As Object
With .document.getElementById("bm_ann_detail_iframe").contentDocument
Set title = .querySelector(".formContentData")
Set data = .querySelectorAll(".ven_table tr")
End With
Dim results(), numberOfRows As Long, i As Long, currentRow As Object, td As Object, c As Long, r As Long
numberOfRows = Round(data.Length / 4, 0)
ReDim results(1 To numberOfRows, 1 To 7)
For i = 0 To numberOfRows - 1
r = i + 1
results(r, 1) = links(u): results(r, 2) = title.innerText
Set currentRow = data.item(i * 4 + 1)
c = 3
For Each td In currentRow.getElementsByTagName("td")
results(r, c) = Replace$(td.innerText, "document.write(rownum++);", vbNullString)
c = c + 1
Next td
Next i
resultCollection.Add results
Set data = Nothing: Set title = Nothing
End If
Next u
.Quit
End With
Dim ws As Worksheet, item As Long
If Not resultCollection.Count > 0 Then Exit Sub
If Not Evaluate("ISREF('Results'!A1)") Then '<==Credit to @Rory for this test
Set ws = Worksheets.Add
ws.NAME = "Results"
Else
Set ws = ThisWorkbook.Worksheets("Results")
ws.cells.Clear
End If
Dim outputRow As Long: outputRow = 2
With ws
.cells(1, 1).Resize(1, UBound(headers) + 1) = headers
For item = 1 To resultCollection.Count
Dim arr()
arr = resultCollection(item)
For i = LBound(arr, 1) To UBound(arr, 1)
.cells(outputRow, 1).Resize(1, 7) = Application.WorksheetFunction.Index(arr, i, 0)
outputRow = outputRow + 1
Next
Next
End With
End Sub
Пример результатов с использованием 2 предоставленных тестовых URL:

Примеры URL-адресов в листе 1:
- http://www.bursamalaysia.com/market/listed-companies/company-announcements/5928057
- http://www.bursamalaysia.com/market/listed-companies/company-announcements/5927201