VBA网页抓取:MSHTML.HTMLDocument转XML点击按钮报错如何解决
错误原因
- 核心逻辑错误:
MSXML2.XMLHTTP是纯静态HTTP请求工具,仅能获取单次请求返回的页面源码。你将源码加载到MSHTML.HTMLDocument后,该文档没有浏览器的JS运行、表单提交能力,修改input值、调用click方法不会触发任何数据更新操作,自然拿不到查询结果。 - 弹窗原因:脱离IE宿主直接调用MSHTML元素的
Click方法时,MSHTML会默认唤起IE浏览器执行点击动作,这就是你看到的无内容IE窗口的来源。 - 冗余逻辑错误:你仅在代码开头请求了一次首页静态内容,后续循环中每次都把HTMLDOC重置为初始的首页源码,没有发起新的请求获取查询结果,所有表单操作都是无效的。
正确实现方案(XMLHTTP版本)
这个网站的查询请求是POST类型,直接构造请求携带股票代码参数即可,无需模拟页面操作:
提前在VBA编辑器的「工具-引用」中勾选
Microsoft XML, v6.0和Microsoft HTML Object Library
Sub KSE_Get_XML_Fixed() Dim XMLp As New MSXML2.XMLHTTP60 Dim HTMLDOC As New MSHTML.HTMLDocument Dim HTMLClass As MSHTML.IHTMLElement Dim HTMLCel As MSHTML.IHTMLElement Dim Cel As Range Dim C As Integer, postData As String ' 遍历要查询的股票代码 For Each Cel In Sheets("Sheet1").Range("A3:A" & Cells(Rows.Count, 1).End(xlUp).Row) If Trim(Cel.Value) = "" Then GoTo nextCel ' 构造POST请求参数 postData = "selscrip=" & Trim(Cel.Value) XMLp.Open "POST", "https://www.ksestocks.com/HistoryHighLow", False ' 添加请求头模拟表单提交 XMLp.setRequestHeader "Content-Type", "application/x-www-form-urlencoded" XMLp.send postData ' 加载返回的查询结果页面 HTMLDOC.body.innerHTML = XMLp.responseText ' 解析目标行 C = 0 For Each HTMLClass In HTMLDOC.getElementsByTagName("tr") If Left(HTMLClass.innerText, 14) = "Last 3 years (" Then For Each HTMLCel In HTMLClass.Children Select Case C Case 1: Cel.Offset(0, 7).Value = HTMLCel.innerText Case 2: Cel.Offset(0, 8).Value = HTMLCel.innerText Case 3: Cel.Offset(0, 9).Value = HTMLCel.innerText Case 4: Cel.Offset(0, 10).Value = HTMLCel.innerText End Select C = C + 1 Next Exit For ' 找到目标行后提前退出循环,提升效率 End If Next nextCel: ' 批量查询时可加100-500毫秒延迟,避免被反爬拦截 Next Set XMLp = Nothing Set HTMLDOC = Nothing End Sub
优化建议
- 可添加User-Agent请求头进一步模拟真实浏览器,降低被反爬拦截的概率
- 增加错误捕获逻辑,处理请求超时、页面结构变动导致元素找不到的异常
- 原IE方案本身因为微软已停止对IE的支持,稳定性会越来越差,优先使用XMLHTTP或者WinHTTP方案
内容的提问来源于stack exchange,提问作者VBAbyMBA
相关产品推荐
相关产品推荐

