VBA结合MSXML2调用getElementsByClassName无法匹配HTML元素如何解决
问题原因
你抓取的站点是基于Angular框架开发的,出现返回结果为0的核心原因有两个:
ng-tns-c329-5、ng-star-inserted属于框架运行时动态生成的类名,不仅会随页面加载随机变化,静态GET请求返回的原始HTML里也不会包含这些动态生成的类属性和对应DOM节点。MSXML2.XMLHTTP只能获取页面初始静态源码,不会执行页面内嵌的JavaScript逻辑,你要抓取的商品列表是JS调用接口动态渲染生成的,自然无法通过静态请求获取到。
解决方案
方案1:直接调用后端接口(优先推荐,效率最高)
打开浏览器开发者工具的「网络」选项卡,刷新目标商品列表页,筛选XHR/Fetch类型的请求,找到返回商品列表数据的后端接口,直接请求该接口拿到JSON数据解析即可,比解析DOM节点效率高很多。
方案2:使用模拟浏览器执行JS渲染(适合不想排查接口的场景)
替换XMLHTTP为IE控件或Selenium Basic等模拟浏览器工具,等待页面JS执行完成后再提取DOM,匹配类名时仅使用固定的业务类名,不要带动态生成的ng前缀类,参考修改后的代码:
Sub Main() Dim IE As New SHDocVw.InternetExplorer Dim HTMLDoc As MSHTML.HTMLDocument Dim Cats As MSHTML.IHTMLElementCollection Dim Cat As MSHTML.IHTMLElement Dim NextHref As String Dim NextURL As String IE.Visible = False ' 调试时可设为True查看浏览器运行过程 IE.navigate URL ' 替换为你的目标页面地址 ' 等待页面基础加载完成 Do While IE.Busy Or IE.readyState <> READYSTATE_COMPLETE DoEvents Loop ' 额外等待1-2秒保证JS渲染完成,可根据页面加载速度调整时长 Application.Wait Now + TimeValue("00:00:02") Set HTMLDoc = IE.document ' 仅使用固定的非动态类名匹配 Set Cats = HTMLDoc.getElementsByClassName("product-grid--tile") Debug.Print Cats.Length ' 此时即可返回正确的节点数量 For Each Cat In Cats NextHref = Cat.getAttribute("href") NextURL = URL & Mid(NextHref, InStr(NextHref, ":") + 2) ListItemsInCats Cat.innerText, NextURL Next Cat IE.Quit Set IE = Nothing End Sub
注意:如果使用Selenium方案需要提前安装Selenium Basic并配置对应浏览器驱动,匹配类名时永远不要选择框架动态生成的类属性,仅选用业务相关的固定类名即可避免匹配失效问题。
内容的提问来源于stack exchange,提问作者John
相关产品推荐
相关产品推荐

