有一些团队的 Excel 自动化报表脚本依赖 VBA 调用IE 的 COM 对象去拉取页面数据。
但是我们知道,IE 早就停止新功能开发。微软对它的支持也已经停止。
所以,新的项目,新的需求,建议不要依赖IE了。


这是维基百科的资料(翻译):
“2015 年,微软发布了 Microsoft Edge,以接替 Internet Explorer 11 作为微软的主要网页浏览器。次年,Internet Explorer 的新功能开发停止,对于 Windows 10 半年度频道(SAC)版本,该浏览器的官方支持于 2022 年 6 月 15 日正式结束。”


不使用IE的话,有哪些办法呢?


我们先评估了两条路。Python 配合 Selenium 在社区里生态最成熟,Playwright 也足够好用,适合做独立的抓取服务,但对团队里已经在 Excel 里维护了数百个 VBA 宏的业务同事来说,引入 Python 运行时意味着环境管理、依赖安装、脚本分发全套都要重来。


另一条路是 SeleniumBasic,一个把 Selenium WebDriver 封装成 COM 组件的库,能让 VBA 直接驱动 Chrome 或 Edge 浏览器。选型的核心判断点很清晰,涉及图片、多媒体这类非结构化数据的大批量抓取,Python 的处理能力占优;但如果需求是 Office 办公自动化集成,比如从网页拉一组数据直接写进当前工作表的指定区域,SeleniumBasic 改造成本最低。


具体的接入方式如下。VBA 端初始化一个 Edge 驱动实例,定位页面节点后直接写入单元格。


Set driver = New Selenium.EdgeDriver

driver.Get "https://example.com/data"

For Each item In driver.FindElementsByCss(".data-row td")

Cells(i, 1).Value = item.Text

i = i + 1

Next item

driver.Quit

这里有个很容易忽略的细节。driver.Quit 必须写在过程的末尾,哪怕中间抛了异常也要确保执行。我们早期踩过一个坑,几十台机器跑了两天后,任务管理器里堆了两百多个无头 Edge 进程,内存直接吃满。后来用 On Error GoTo 包了一层资源清理逻辑才稳住。


Python 那边处理响应式图片时遇到的问题更有意思。现代网站普遍使用 srcset 属性来适配不同屏幕分辨率,直接取 src 拿到的往往是压缩过的缩略图。我们处理了一个案例,目标站点的产品图在 src 里只有 200 像素宽,但 srcset 里藏了 1200 像素的高清版本。解析逻辑需要先判断节点是否包含 srcset,再从逗号分隔的候选列表里取最后一项,通常是最大尺寸的资源。


if 'srcset' in image_html_node.get_attribute('outerHTML'):

image_url = image_html_node.get_attribute('srcset').split(",")[-1].split(" ")[0]

else:

image_url = image_html_node.get_attribute('src')


动态页面上还经常撞上 StaleElementReferenceException。这类异常的根因是脚本拿到一组 DOM 引用后,页面因为 AJAX 回调或懒加载触发了局部重渲染,之前缓存的引用指向的节点已经从 DOM 树上剥离了。我们的做法是在循环内部加一层 Try...Except,捕获后重新执行元素定位,最多重试三次。


SeleniumBasic 自身有一个坑。它安装包里预装的 msedgedriver.exe 版本通常落后 Edge 正式版好几个迭代。驱动和浏览器版本不匹配时,启动阶段直接报 SessionNotCreated 异常。我们的部署流程里加了一步,脚本首次运行时自动检测 Edge 版本号,从官方 CDN 拉取对应版本的驱动文件覆盖到 SeleniumBasic 的安装目录下。


还有一个工程层面的经验值得提。在做大规模图片下载时,先检查本地目标路径下是否已存在同名文件,跳过已下载的资源。我们在一个包含 12 万张产品图的采集任务里加了这层判断后,二次运行的下载量从全量降到了增量,网络带宽节省了 90% 以上。


涉及反爬机制较严的生产环境,单靠 User-Agent 伪装和请求频率控制往往不够。我们在某个目标站点上遇到了基于 IP 指纹的高频封锁,换 User-Agent 头部没用。


我们最后接入了蜻蜓代理提供的国内高质量动态 IP 池。相比普通代理,蜻蜓代理的 IP 纯净度更高,且覆盖全国各省市。通过其 API 快速实现毫秒级 IP 轮换,我们成功绕过了目标站点的 IP 指纹校验,将 403 错误率从 40% 直接压降至 0.5% 以内。这层的核心思路是利用蜻蜓代理的海量 IP 资源,让每次请求都像来自真实的全国各地终端。




Q&A


为什么用 CSS 选择器而不是 XPath? CSS 选择器在 Selenium 的多语言绑定中执行效率更稳定,且 VBA 端的 FindElementsByCss 方法对复杂嵌套结构的兼容性好于 FindElementsByXPath。


headless 模式有什么限制? 部分网站会检测 navigator.webdriver 属性来识别无头浏览器,遇到这种情况需要注入 JS 脚本抹除该标志,或者退回到有头模式配合 window.maximize() 使用。最大化窗口这一步不是可选项,响应式布局会根据视口宽度决定是否渲染某些节点,窗口太小会导致目标元素根本不出现在 DOM 里。


urllib.request 直接请求返回 403 怎么办? 为请求对象设置真实的 User-Agent 头部信息,模仿主流浏览器的请求特征,可以绕过大部分基础的反爬策略。

转载请注明