问题
I have checked that both browser-generated page and VBA XMLHTTP request's string response have the same tree structure, with a tag being a child of aside.
Unfortunately when I want to return bookie name, which is title attribute of a, I get an error accessing 1st child of aside. It comes out that I need to use code assuming that a tag is a sibling of aside to get it working:
Required reference: Microsoft HTML Library
Sub SendRequest()
Dim XMLHTTP As Object: Set XMLHTTP = CreateObject("MSXML2.XMLHTTP.6.0")
Dim htmlEle1 As IHTMLElement
Dim htmlDoc As New HTMLDocument
Dim urlName As String
urlName = "https://www.oddschecker.com/golf/the-masters/2018-us-masters/winner"
With XMLHTTP
.Open "GET", urlName, False
.send
htmlDoc.body.innerHTML = .responseText
For Each htmlEle1 In htmlDoc.getElementsByClassName("eventTableHeader")(0).Children
If InStr(htmlEle1.className, "bookie-area") <> 0 Then
Debug.Print htmlEle1.Children(1).getAttribute("title")
End If
Next htmlEle1
End With
End Sub
Does this behavior have something to do with the fact that aside is HTML5 element and VBA thinks that it is a semi-closing tag?
回答1:
So this took awful lot of time to figure out. The issue is that you can't do it this way. When you launch a new HTMLDocument
the documentMode
of it is by default set to 5
So when we load a write any HTML inside it, it has no idea of these HTML5 tags and it just does its own correction. This is as good as you running HTML5 site in a IE6 browser or something. Unfortunately there is no way I could find out which would allow us to create/parse document with a higher documentMode
Update
Thanks to @FlorentB for pointing out that emulation mode works on the MSHTML library as well. I was already aware of the same from below
Embedding Youtube Videos in webbrowser. Object doesn't support property or method
But I assumed it won't work for the MSHTML library. I have now tested it by running below command
REG ADD "HKCU\Software\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION" /v excel.exe /t REG_DWORD /d 11001 /f
And then the existing code and it works.
Alternat approach
If setting the registry key needs to be avoided for any reason then one can use the IE COM Browser directly.
You can do this by adding a reference to Microsoft Internet Controls
and then execute the below code
Sub dothis()
Dim XMLHTTP As Object: Set XMLHTTP = CreateObject("MSXML2.XMLHTTP.6.0")
Dim htmlEle1 As IHTMLElement
Dim htmlDoc As HTMLDocument
'Set htmlIDoc = htmlDoc
Dim urlName As String
urlName = "https://www.oddschecker.com/golf/the-masters/2018-us-masters/winner"
Dim ie As InternetExplorerMedium
Set ie = New InternetExplorerMedium
ie.Visible = False
ie.navigate2 urlName
While ie.readyState <> READYSTATE_COMPLETE
DoEvents
Wend
Set htmlDoc = ie.document
Debug.Print (htmlDoc.documentMode)
For Each htmlEle1 In htmlDoc.getElementsByClassName("eventTableHeader")(0).Children
If InStr(htmlEle1.className, "bookie-area") <> 0 Then
Debug.Print htmlEle1.Children(0).children(0).getAttribute("title")
End If
Next htmlEle1
End Sub
And now you can see that a
is a child of aside
来源:https://stackoverflow.com/questions/49501406/vba-doesnt-read-xmlhttp-requests-response-according-to-its-tree-structure