为何使用Get方法与IE.navigate时getElement系列方法返回结果不同?
解决XMLHTTP加载HTML后DOM查找方法失效的问题
嘿,我来帮你搞定这个困扰你好久的问题!你提到用IE控件加载网页时getElementsByClassName这类方法好好的,但换成XMLHTTP的GET请求后就返回空值,这事儿我之前也碰到过,核心原因在于两种加载HTML的方式本质差得挺多的。
先说说为啥会这样
- DOM解析不完整:你直接把XMLHTTP拿到的响应文本塞给
HTMLDoc.body.innerHTML,这相当于只给了文档的一部分内容,HTMLDocument并没有像浏览器那样完整解析整个页面(包括DOCTYPE、head里的样式和脚本声明这些),导致DOM结构不规范,元素查找方法自然没法正常工作。 - 动态元素搞的鬼:Google搜索框的那些元素(比如
gsfi类的)很多是页面加载后通过JavaScript动态生成的!XMLHTTP只能拿到页面的静态源码,根本不会执行页面里的JS,所以自然找不到这些后来才出现的元素。而IE控件是像真实浏览器一样会跑JS渲染页面的,所以能拿到这些元素。
给你两个可行的解决方案
方案1:让HTMLDocument完整解析整个页面
别只赋值body.innerHTML了,改用write方法把整个响应文本写入HTMLDocument,这样它会像浏览器一样完整构建DOM:
Dim XMLPage As New MSXML2.XMLHTTP60 Dim HTMLDoc As New MSHTML.HTMLDocument Dim URL As String Dim Element1 As MSHTML.IHTMLElement Dim Element2 As MSHTML.IHTMLElement URL = "https://www.google.nl/?gfe_rd=cr&dcr=0&ei=KXNcWsHNJ9OB4gTcjqvwCA" XMLPage.Open "GET", URL, False XMLPage.send ' 关键步骤:用open+write+close让文档完整解析 HTMLDoc.open HTMLDoc.write XMLPage.responseText HTMLDoc.close Set Element1 = HTMLDoc.getElementsByClassName("gsfi")(0) Set Element2 = HTMLDoc.getElementById("lst-ib") If Not Element2 Is Nothing Then Debug.Print Element2.className Else Debug.Print "没找到目标元素" End If
方案2:应对动态生成的元素
如果目标元素是JS动态生成的,XMLHTTP这条路就走不通了,这时候你有两个选项:
- 优化IE控件的使用:虽然IE确实慢一点,但你可以把
IE.Visible = False关掉,这样速度会提升不少,而且能确保拿到完整的渲染后DOM。 - 分析页面JS逻辑:如果一定要用XMLHTTP,就得去扒页面的JS代码,看看那些元素是怎么生成的,然后手动从响应里提取需要的信息,或者模拟生成元素。不过这个方法复杂度比较高,而且Google页面经常改结构,不太稳定。
额外提个醒
Google的页面结构经常更新,靠类名、ID定位元素很容易失效。如果是做搜索相关的操作,建议用Google官方的API,比自己爬页面靠谱多啦!
内容的提问来源于stack exchange,提问作者Jonathan van Kleef
相关产品推荐
相关产品推荐

