VBA网页抓取:Internet Explorer与XMLHTTP请求结果差异排查
这个问题其实挺常见的,核心差异在于IE是完整的浏览器环境,而XMLHTTP只是单纯的HTTP请求工具,两者处理网页的逻辑完全不同,咱们一步步拆解原因和解决方案:
核心差异原因
1. JavaScript动态渲染的区别
IE会像你日常用浏览器一样,加载页面后自动执行所有JavaScript代码,生成最终的DOM结构(包括你要抓取的listisq1元素)。但XMLHTTP仅仅获取服务器返回的原始HTML源码,如果目标元素是页面加载后通过JS动态生成的,那原始源码里根本没有这个元素,自然getElementById会返回Nothing,写入的就是空字符串。
2. 请求头的缺失
浏览器发送请求时会附带一堆标识身份的请求头(比如User-Agent、Referer等),很多网站会通过这些头判断请求是否来自真实浏览器。XMLHTTP默认的请求头非常简单,可能被网站识别为非浏览器请求,返回的内容不完整或者直接跳过动态内容的渲染逻辑。
3. Session/Cookie的处理
IE会自动管理网站的Cookie和Session,而XMLHTTP默认不会携带之前的Cookie(除非你手动处理)。如果目标网站需要验证Session才能返回完整内容,XMLHTTP的请求就得不到正确响应。
解决方案尝试
先试试给XMLHTTP添加模拟浏览器的请求头,看看能不能拿到完整内容:
Dim page As MSHTML.HTMLDocument Dim req As New MSXML2.XMLHTTP60 Dim ele As MSHTML.IHTMLElement Dim fso As Scripting.FileSystemObject Dim st As Scripting.TextStream req.Open "GET", "http://www.scstrade.com/stockscreening/SS_CompanySnapShotQF.aspx?symbol=LUCK", False ' 添加模拟浏览器的关键请求头,让网站认为你是真实用户访问 req.setRequestHeader "User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36" req.setRequestHeader "Referer", "http://www.scstrade.com/stockscreening/" req.setRequestHeader "Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8" req.send If req.Status <> 200 Then MsgBox "请求失败!" Exit Sub End If Set page = New MSHTML.HTMLDocument page.body.innerHTML = req.responseText Set ele = page.getElementById("listisq1") ' 先判断元素是否存在,避免报错 If Not ele Is Nothing Then Set fso = New Scripting.FileSystemObject Set st = fso.CreateTextFile(ThisWorkbook.Path & "\XMLHTTPscrape.txt") st.Write ele.innerText st.Close MsgBox "抓取成功!" Else MsgBox "未找到目标元素,说明内容是JavaScript动态生成的!" End If
如果添加请求头后还是找不到listisq1,那基本可以确定内容是JS动态渲染的,这时候XMLHTTP就没办法处理了——因为它不执行JS。这种情况下你的IE方法能工作是合理的,但IE已经被微软淘汰,推荐你换成Selenium VBA(支持Chrome/Firefox等现代浏览器,能执行JS),或者通过浏览器开发者工具分析网站的AJAX接口,直接请求数据源接口(效率更高)。
内容的提问来源于stack exchange,提问作者mobeen anwar

