Методы VBA htmlDoc.getElementBy* ничего не возвращают

#html #vba #web-scraping

#HTML #vba #очистка веб-страниц

Вопрос:

Приветствую всех.


ЦЕЛЬ

Я хочу открыть flashscore.com и получают данные, относящиеся к футбольным матчам. Мне нужны все матчи этого сезона, поэтому ссылку «Показать больше матчей» придется щелкнуть один или несколько раз.


ОГРАНИЧЕНИЯ

  • Мне нужно сделать это с помощью VBA
  • Этот сайт не поддерживает Internet Explorer
  • Я не могу ничего установить на ПК, который будет использоваться, поэтому Selenium отключен в качестве опции

Принимая во внимание все вышесказанное, похоже, единственным оставшимся вариантом является Microsoft XML, v6.0 библиотека.


ЧТО я ПРОБОВАЛ

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

 Option Explicit

Sub Get_Matches()
'REFERENCE TO Microsoft XML, v6.0
Dim httpReq As New MSXML2.XMLHTTP60
Dim doc As MSHTML.HTMLDocument
Dim eleCol As Object
Dim ele As MSHTML.HTMLHtmlElement
    
'Open site and get html. In comments:things proposed by others but seemed to make no change.
    httpReq.Open "GET", "https://www.flashscore.com/football/england/premier-league-2019-2020/results/"
    'httpReq.setRequestHeader "If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT"
    httpReq.send
    Set doc = New MSHTML.HTMLDocument
    doc.body.innerHTML = httpReq.responseText
    'doc.body.innerHTML = httpReq.responseBody


'Tried to get the div containing the first match:
    Set ele = doc.getElementById("g_1_2JDks1o7") '--> returns nothing

'Tried to get the "Show more matches" link:
    Set ele = doc.getElementsByClassName("event__more")(0) '--> returns nothing

'Tried to get the first ancestor that has an id:
    Set ele = doc.getElementById("live-table") '--> returns nothing


'Tried to get all <a> elements and then narrow them down till I find the "Show more matches" link:
    Set eleCol = doc.getElementsByTagName("a")
    For Each ele In eleCol
        If ele.href Like "*[#]*" And ele.innerText = "Show more matches" Then 
            Exit For
        End If
    Next ele
    ele.Click '--> I get the "Show more matches" link, but nothing seems to change
'Someone suggested firing onclick event.
    ele.FireEvent "onclick" '--> did nothing


'Some people suggested waiting.
'So I tried this:
    Do
        DoEvents
    Loop While doc.readyState = "loading"
    If doc.readyState <> "complete" Then GoTo ERROR_END
    Set doc = New MSHTML.HTMLDocument
    doc.body.innerHTML = httpReq.responseText
'and the Delay_Code_By function below,
    Set ele = doc.getElementById("live-table") '--> but still returns nothing


'Some people suggested looping, so the document gets loaded first.
    Do: Set ele = doc.getElementById("live-table"): DoEvents: Loop While ele Is Nothing '--> resulted to infinite loop.
    Do: Set eleCol = doc.getElementsByClassName("event__more"): DoEvents: Loop Until eleCol.Length > 0 '--> resulted to infinite loop.


'This block extracts html in a txt file in desktop, to help me see it, as it is at runtime.
'------------------------------------------------------------------------------------------
'    Dim fso As Scripting.FileSystemObject
'    Dim txtFile As Scripting.TextStream
'    Set fso = New Scripting.FileSystemObject
'    Set txtFile = fso.OpenTextFile(CreateObject("WScript.Shell").SpecialFolders("Desktop") amp; "output.txt", 2, True, TristateTrue)
'    txtFile.Write httpReq.responseText
'    txtFile.Close
'    Set txtFile = Nothing
'    Set fso = Nothing
'------------------------------------------------------------------------------------------
'Inside the txt file I found html code that onclick calls some kind of function:

'Tried to call this function:
    doc.parentWindow.execScript "document.body.classList.toggle('loading', true);", "JScript" '--> throws automation error (probably there's some error with my syntax).

'I also tried to call this function:
    doc.parentWindow.execScript "function(){return cjs.Api.loader.get('cjs').call(function(_cjs){loadMoreGames(_cjs);});};" '--> which did not throw error but did nothing.


    Exit Sub
ERROR_END:
    MsgBox "error"
End Sub


Public Sub Delay_Code_By(seconds As Integer)
Dim endTime As Date
    endTime = DateAdd("s", seconds, Now)
    Do While Now < endTime
        DoEvents
    Loop
End Sub
  

ВОПРОСЫ

  1. Если есть какой-либо другой вариант, которого мне не хватает, кроме использования Microsoft XML, v6.0 библиотеки, пожалуйста, скажите мне попробовать его.
  2. Насколько я понимаю, проблема в том, что элементы, которые я пытаюсь получить, отсутствуют в тот момент, когда я пытаюсь их получить. Если я прав, может ли кто-нибудь, пожалуйста, объяснить мне, почему это происходит, и возможное решение этой проблемы? Если я ошибаюсь, пожалуйста, укажите мне правильное направление.Спасибо.

Обновить

Я публикую этот скриншот на основе комментария @QHarr о просмотре вкладки сеть / xhr. вкладка network xhr

Комментарии:

1. Если очистка разрешена, посмотрите, можете ли вы найти xhr на вкладке сеть, которая используется для обновления страницы с требуемым содержимым. Нажмите показать больше и посмотрите, что сгенерировано на вкладке сеть.

2. Я сделал то, что вы предложили, и что-то действительно генерируется. Не могли бы вы вкратце объяснить мне, что делается? Я обновлю вопрос скриншотом, чтобы увидеть точно.

3. Если страница динамически обновляется, вы можете увидеть эти обновления на вкладке сеть и, возможно, найти свои данные в одном из этих дополнительных запросов.