Python3 urllib爬取MOD站点触发403 Forbidden及多请求头定义错误
403报错核心根因
- 抓错请求头来源:Wireshark捕获的
ocsp.pki.goog请求头属于浏览器证书校验的OCSP协议专用请求,和访问MOD站点的页面请求完全无关。请求中携带Content-Type: application/ocsp-request这类OCSP专属字段,会被服务器直接判定为异常流量。 - 请求头值格式违规:手动在每个请求头的 value 末尾添加
\r\n转义字符,urllib本身会自动拼接HTTP协议要求的头分隔符,手动添加的转义字符会被解析为头值的一部分,直接触发multiple headers defined类的协议校验报错,部分服务器识别到这类格式异常会直接返回403。 - 重复定义自动生成的头:urllib会根据请求URL自动生成Host头,根据请求体长度自动生成Content-Length头,手动重复添加这两个字段是之前触发400 Bad Request的直接原因。
- 核心头特征缺失:当前使用的头列表缺少浏览器访问网页时必带的文档类Accept字段、
Upgrade-Insecure-Requests字段,请求特征和正常浏览器访问差距过大,会被反爬规则拦截。 - 循环逻辑漏洞:原代码
while mods的判断条件是列表非空,全程没有对mods列表做清空、弹出操作,循环会永久重复请求第一个MOD的路径,高频重复请求同一个地址很容易触发服务器的临时反爬拦截,返回403。
修正后可直接运行的代码
from urllib.request import Request, urlopen import gzip mods = ['mod1', 'mod2', ...] # 已验证路径有效性的MOD列表 # 适配Firefox 85的标准网页访问请求头,剔除OCSP专属字段 VALID_HEADERS = { 'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:85.0) Gecko/20100101 Firefox/85.0', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8', 'Accept-Language': 'en-US,en;q=0.5', 'Accept-Encoding': 'gzip, deflate', 'Connection': 'keep-alive', 'Upgrade-Insecure-Requests': '1' } count = 0 while count < len(mods): url = f'https://Domain/{mods[count]}' req = Request(url, headers=VALID_HEADERS) raw_content = urlopen(req).read() # 兼容gzip压缩响应,避免解码失败 try: html = gzip.decompress(raw_content).decode('utf-8') except gzip.BadGzipFile: html = raw_content.decode('utf-8') count += 1
后续排查注意事项
- 抓请求头时不要选择OCSP、静态资源加载类的后台自动请求,要在浏览器开发者工具的网络面板中,选中目标页面的主文档请求,复制对应请求头列表。
- 所有请求头值不要手动添加
\r\n、\t这类控制字符,避免触发协议解析异常。 - 不要手动定义Host、Content-Length、Cookie这类urllib自动生成的字段,避免重复定义触发拦截。
- 配置了
Accept-Encoding: gzip, deflate头的情况下,必须对应增加gzip解压逻辑,否则直接对压缩后的二进制内容做utf-8解码会触发解码错误。
内容的提问来源于stack exchange,提问作者TLShandshake
相关产品推荐
相关产品推荐

