Отвечая на этот вопрос, я заметил какое-то странное для меня поведение.В коде из этого ответа, показанном ниже, я ожидал, что переменные names
будут статическими nodeList: Object\DispStaticNodeList
.Это обычный возврат для querySelectorAll с классом VBA MSHTML.HTMLDocument.
Из документации API
Метод Document querySelectorAll () возвращает статический (не действующий) NodeList, представляющий список элементов документа, которые соответствуют указанной группе селекторов.
Однако в этом случае возвращаемое значение в Locals равно Object
, и при использованииИмя типа (имена) - JScriptTypeInfo
.Ранее я читал этот впечатляющий пост и немного знаком с ScriptControl
, но это не объясняет мне, что здесь происходит.
Почему querySelectorAll возвращает JScriptTypeInfo
объектвместо статического nodeList.И почему это JScriptTypeInfo
характерно для querySelectorAll
, а не getElementsByClassName
?Я чувствую, что это должно быть связано с интерфейсами классов, но что на этой странице приводит к Object\JScriptTypeInfo
, а не Object\DispStaticNodeList
?
Другие наблюдения:
- Вы можете использовать
getElementsByClassName
очень хорошо:
Set names = .getElementsByClassName("selection-left-selection-name")
'?typename(names) >> DispHTMLElementCollection
Объект проходит тест IsObject и может использоваться с Set, но впоследствии может рассматриваться как строка:
Debug.Print IsObject(names) '>> True
Debug.Print names '>> "[object HTMLDivElement],[object HTMLDivElement],[object HTMLDivElement],....."
Я предполагаю, что это как-то связано свозвращается реальный объект, но по умолчанию вызывается элемент с Debug.Print names
.Но чтобы это работало, мы предполагаем, что больше не получаем массив объектов в качестве возврата.В противном случае это будет цепочка вызова по умолчанию .defaultMember.defaultMember.Связанный QA от @SMeaden гласит:
JScriptTypeInfo - это то, что нужно показать в окне просмотра VBA IDE и возвращении функции VBA TypeName (), но которая действительно скрывает ряд объектов, которые можно найтив JScript.dll.Я полагаю, это можно назвать полиморфным, возможно, лучше описать его как позднее связывание.Для просмотра возможностей используйте Tools-References и перейдите к JScript.dll.
В таком случае, как я могу проверить элемент по умолчанию (я на 64-битной машине)?Я предполагаю, что не могу добавить в ScriptControl dll, так как я думаю, что они требуют 32 бит?Эти более поздние пункты - больше размышлений.
Мне было интересно, связано ли это с
querySelectorAll
с использованием селекторов css, но я заметил следующее: С Python selenium + IE с использованием селекторов Css (так как я не могу тестировать с VBA Selenium Basic), я не вижу такого поведения, хотяРеализация класса
webElement
.Я получаю ожидаемое
<class 'list'>
в качестве возврата.Я включаю скрипт для VBA selenium, который я не могу проверить, но должен работать как тест для запуска других.
Код для воспроизведения:
Option Explicit
Public Sub GetOddsIE()
Dim d As InternetExplorer, names As Object, t as Date, button As Object, ws As Worksheet
Const MAX_WAIT_SEC As Long = 10
Set d = New InternetExplorer
Set ws = ThisWorkbook.Worksheets("Sheet1")
Const URL = "https://sports.ladbrokes.com/en-af/betting/golf/golf-all-golf/us-masters/2020-us-masters/228648232/"
With d
.Visible = True
.Navigate2 URL
While .Busy Or .ReadyState <> 4: DoEvents: Wend
With .Document
t = Timer
Do
DoEvents
On Error Resume Next
Set button = .querySelector(".expandable-below-container-button span")
On Error GoTo 0
If Timer - t > MAX_WAIT_SEC Then Exit Do
Loop While button Is Nothing 'wait for element to be present
If button Is Nothing Then Exit Sub
button.Click 'click on show more
Set names = .querySelectorAll(".selection-left-selection-name")
Debug.Print IsObject(names)
Debug.Print TypeName(names)
Debug.Print names
End With
Stop
.Quit
End With
End Sub
Css селекторы через Python selenium + IE:
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
d = webdriver.Ie()
d.get('https://sports.ladbrokes.com/en-af/betting/golf/golf-all-golf/us-masters/2020-us-masters/228648232/')
WebDriverWait(d,10).until(EC.presence_of_element_located((By.CSS_SELECTOR, ".expandable-below-container-button"))).click()
names = d.find_elements_by_css_selector('.selection-left-selection-name')
print(type(names))
d.quit()
Дает
>> <class 'list'>
непроверенный VBA селен с IE (я не могу проверитьэто):
Public Sub GetOdds() 'Not tested
Dim d As WebDriver, names As Object, button As Object, t As Date
Set d = New IEDriver
Set ws = ThisWorkbook.Worksheets("Sheet1")
Const URL = "https://sports.ladbrokes.com/en-af/betting/golf/golf-all-golf/us-masters/2020-us-masters/228648232/"
With d
.Start "Chrome"
.get URL
t = Timer
Do
DoEvents
On Error Resume Next
Set button = .FindElementByCss(".expandable-below-container-button span")
On Error GoTo 0
If Timer - t > MAX_WAIT_SEC Then Exit Do
Loop While button Is Nothing
If button Is Nothing Then Exit Sub
Set names = .FindElementsByCss(".selection-left-selection-name")
Debug.Print IsObject(names)
Debug.Print names.Text '<should fail if webElementsCollection
Stop
.Quit
End With
End Sub