为何部分站点可通过JavaScript加载却无法用ASP服务端XMLHTTPREQUEST加载?
为什么Classic ASP的XMLHTTP请求失败,但客户端AJAX可以访问?
这个问题在服务端爬虫/请求场景里很常见,核心原因是服务端XMLHTTP请求和客户端浏览器AJAX的运行环境存在关键差异,下面我会拆解具体原因并给出可落地的修复方案:
主要原因分析
1. TLS协议版本不兼容
绝大多数现代网站已经彻底禁用了SSL3、TLS1.0这类旧版加密协议,只支持TLS1.2及以上版本。但Classic ASP默认使用的MSXML2.XMLHTTP.6.0并没有自动启用这些新版本协议,导致请求时握手失败;而客户端浏览器会自动适配最新的TLS版本,所以能正常访问目标站点。
2. 请求头不完整
虽然你设置了User-Agent,但很多网站会通过验证多组请求头来区分真实浏览器请求和服务端爬虫请求。你的服务端请求缺少了Accept、Accept-Language、Accept-Encoding等关键标识头,直接被站点的反爬机制拦截了。
3. 服务器端网络限制(可能性较低)
如果你的ASP服务器处于内网环境,或者有防火墙/代理拦截了特定域名的出站请求,也会导致部分URL无法访问;而客户端是直接连接互联网,不受此限制。不过你提到部分URL能正常加载,这个可能性相对较小,但可以作为后续排查方向。
修复后的代码示例
我针对上述问题修改了你的代码,重点补充了TLS协议配置和完整请求头:
<% 'rss_url = "https://www.nationalgeographic.com/science/2019/06/opal-fossils-reveal-new-species-dinosaur-australia-fostoria" '原无法加载URL rss_url = "https://www.nbcnews.com/news/us-news/ex-minneapolis-officer-who-killed-justine-damond-sentenced-12-5-n1013926" '原无法加载URL 'rss_url = "https://www.reuters.com/article/us-usa-saudi-arms/republican-democratic-senators-seek-to-block-trump-saudi-arms-sales-idUSKCN1T61PL" '可加载URL Dim objHTTP Set objHTTP = Server.CreateObject("MSXML2.XMLHTTP.6.0") ' 关键:强制启用TLS1.2协议(解决握手失败问题) ' 0x3300 对应TLS1.2,若需要兼容TLS1.1/1.0可改为13056(0x3300+0x3200+0x3100) objHTTP.SetOption 2, &H3300 Err.Clear ON ERROR RESUME NEXT objHTTP.Open "GET", rss_url, False ' 补充完整的浏览器请求头,模拟真实浏览器行为 objHTTP.setRequestHeader "User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36" objHTTP.setRequestHeader "Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8" objHTTP.setRequestHeader "Accept-Language", "en-US,en;q=0.5" objHTTP.setRequestHeader "Accept-Encoding", "gzip, deflate, br" objHTTP.setRequestHeader "Connection", "keep-alive" objHTTP.setRequestHeader "Upgrade-Insecure-Requests", "1" aErr = Array(Err.Number, Err.Description) On Error GoTo 0 If 0 = aErr(0) Then On Error Resume Next objHTTP.Send aErr = Array(Err.Number, Err.Description) On Error GoTo 0 Select Case True Case 0 <> aErr(0) response.write "send failed: " & aErr(0) & " - " & aErr(1) Case 200 = objHTTP.status response.write rss_url & "<br>Status: " & objHTTP.status & " " & objHTTP.statusText & "<hr>" sdata = BinaryToString(objHTTP.ResponseBody) response.write sdata Case Else response.write "further work needed:<br>" response.write rss_url & "<br>Status: " & objHTTP.status & " " & objHTTP.statusText End Select Else response.write "open failed: " & aErr(0) & " - " & aErr(1) End If If Err.Number <> 0 Then Response.Write "<br>NO feed from ..." End If Set objHTTP = Nothing Function BinaryToString(byVal Binary) BinaryToString = "" Dim BinaryStream Set BinaryStream = CreateObject("ADODB.Stream") BinaryStream.Type = 1 ' adTypeBinary BinaryStream.Open BinaryStream.Write Binary BinaryStream.Position = 0 BinaryStream.Type = 2 ' adTypeText BinaryStream.CharSet = "UTF-8" BinaryToString = BinaryStream.ReadText Set BinaryStream = Nothing End Function %>
关键修改说明
- TLS协议配置:通过
objHTTP.SetOption 2, &H3300强制启用TLS1.2,这是解决现代站点握手失败的核心步骤。 - 完整请求头:添加了浏览器常用的标识头,让服务端请求更接近真实用户的浏览器请求,避免被反爬规则拦截。
- 错误提示优化:在错误信息中添加了分隔符,方便你快速定位具体错误代码和描述。
如果修改后仍然无法访问,建议在服务器上用curl或telnet测试目标域名的连通性,排查是否有防火墙或代理限制了出站请求。
内容的提问来源于stack exchange,提问作者Astralis Lux
相关产品推荐
相关产品推荐

