VBA脚本用ServerXMLHTTP代理请求卡第一个代理,如何遍历全部代理?
解决VBA ServerXMLHTTP代理遍历卡住的问题
看起来你的脚本卡在第一个代理的核心原因是复用了同一个ServerXMLHTTP对象,导致前一次请求的状态、错误或资源残留影响了后续循环。另外,错误处理的方式也可能掩盖了问题,让脚本无法正常推进到下一个代理。下面是具体的修复方案和修改后的代码:
问题分析
- 对象复用导致状态残留:你在循环外创建了
Http和Html对象,每次请求后这些对象的内部状态(比如错误标记、未释放的连接)不会自动重置,可能导致后续请求无法正常发起。 - 错误处理范围过大:
On Error Resume Next覆盖了整个With Http块,可能隐藏了send或responseText解析中的错误,导致代码停在某个步骤无法继续循环。 - 超时参数不合理:你设置的连接/发送超时长达10分钟(600000毫秒),如果第一个代理不可用,脚本会等待很久才会超时,看起来像是“卡住”了。
修复方案
- 每次循环重新创建对象:在
For Each循环内部初始化ServerXMLHTTP60和HTMLDocument,确保每次请求都是全新的上下文。 - 精准控制错误处理:只在
send和readyState等待阶段使用错误捕获,之后立即恢复错误处理,便于排查问题。 - 调整超时参数:缩短连接和发送超时(比如设为5秒),避免长时间等待;接收超时可以适当延长(比如30秒)。
- 清理对象引用:每次循环结束后释放对象,避免内存泄漏。
修改后的代码
Sub MakeProxiedRequests() Dim Http As ServerXMLHTTP60, Html As HTMLDocument Dim elem As Object, proxyList As Variant, oProxy As Variant Dim requestSuccess As Boolean Dim startTime As Double proxyList = Array( _ "191.96.42.184:3129", _ "138.197.108.5:3128", _ "35.245.145.147:8080", _ "173.46.67.172:58517", _ "191.96.42.82:3129", _ "157.55.201.224:8080", _ "67.205.172.239:3128", _ "191.96.42.106:3129" _ ) For Each oProxy In proxyList requestSuccess = False startTime = Timer Debug.Print "Trying with proxy: " & oProxy ' 每次循环创建新的对象实例 Set Http = New ServerXMLHTTP60 Set Html = New HTMLDocument With Http .Open "GET", "https://stackoverflow.com/questions/tagged/web-scraping", True .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" .setProxy 2, oProxy ' 调整超时:连接超时5秒,发送超时5秒,接收超时30秒 .setTimeouts 5000, 5000, 30000, 30000 On Error Resume Next .send ' 等待请求完成或超时 While .readyState < 4 DoEvents ' 额外检查是否超时(可选,避免无限等待) If Timer - startTime > 35 Then ' 比接收超时多5秒缓冲 Exit While End If Wend On Error GoTo 0 ' 检查请求是否成功 If .Status = 200 Then Html.body.innerHTML = .responseText Set elem = Html.querySelectorAll(".summary .question-hyperlink") If Not elem Is Nothing And elem.Length > 0 Then Debug.Print "Success! First question: " & elem(0).innerText requestSuccess = True End If End If End With ' 释放对象 Set Http = Nothing Set Html = Nothing Set elem = Nothing If Not requestSuccess Then Debug.Print "Failed with proxy: " & oProxy End If Next oProxy End Sub
关键修改说明
- 对象实例化移到循环内:每次循环都创建新的
ServerXMLHTTP60和HTMLDocument,彻底避免状态残留问题。 - 优化错误处理:仅在
send和等待阶段使用On Error Resume Next,之后立即恢复正常错误处理,防止隐藏其他问题。 - 超时参数调整:缩短连接和发送超时,减少等待时间;同时添加了一个超时检查的额外保险,避免因
readyState不更新导致的无限等待。 - 状态检查:通过
.Status = 200判断请求是否成功,而不是仅仅依赖元素是否存在,判断逻辑更准确。
这样修改后,脚本会逐个遍历所有代理,无论某个代理是否可用,都会继续执行下一个,直到整个列表处理完毕。
内容的提问来源于stack exchange,提问作者robots.txt
相关产品推荐
相关产品推荐

