VBA 不会根据其树结构读取 XMLHTTP 请求的响应 [英] VBA doesn't read XMLHTTP request's response according to its tree structure

查看:32
本文介绍了VBA 不会根据其树结构读取 XMLHTTP 请求的响应的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已检查浏览器生成的页面和 VBA XMLHTTP 请求的字符串响应是否具有相同的树结构,a 标记是 aside 的子级.

不幸的是,当我想返回 bookie name(a 的 title 属性)时,我在访问 aside 的第一个孩子时出错.结果表明,我需要使用代码,假设 a 标签是 aside 的兄弟标签才能使其正常工作:

需要参考:Microsoft HTML 库

Sub SendRequest()Dim XMLHTTP As Object: Set XMLHTTP = CreateObject("MSXML2.XMLHTTP.6.0")将 htmlEle1 调暗为 IHTMLElementDim htmlDoc 作为新的 HTMLDocument将 urlName 变暗为字符串urlName = "https://www.oddschecker.com/golf/the-masters/2018-us-masters/winner"使用 XMLHTTP.打开GET",urlName,假.发送htmlDoc.body.innerHTML = .responseText对于每个 htmlEle1 在 htmlDoc.getElementsByClassName("eventTableHeader")(0).Children如果 InStr(htmlEle1.className, "bookie-area") <>0 那么Debug.Print htmlEle1.Children(1).getAttribute("title")万一下一个 htmlEle1结束于结束子

这种行为是否与 aside 是 HTML5 元素而 VBA 认为它是半结束标记的事实有关?

解决方案

所以这花了很多时间才弄明白.问题是你不能这样做.当你启动一个新的 HTMLDocument 时,它的 documentMode 默认设置为 5

所以当我们加载一个写入其中的任何 HTML 时,它不知道这些 HTML5 标签,它只是自己进行更正.这与您在 IE6 浏览器或其他东西中运行 HTML5 站点一样好.不幸的是,我无法找出哪个允许我们使用更高的 documentMode 创建/解析文档

更新

感谢@FlorentB 指出模拟模式也适用于 MSHTML 库.我已经从下面意识到了这一点

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?

解决方案

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

这篇关于VBA 不会根据其树结构读取 XMLHTTP 请求的响应的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆