Python使用requests批量下载HTML页面累计2万后返回403错误求助
问题原因分析
- 请求头特征异常:requests默认发送的
User-Agent会明确标识为Python请求,多数站点反爬机制会识别非浏览器UA的请求,累计请求量达到阈值后直接拦截返回403,浏览器可正常访问正是因为浏览器携带了完整的合法UA及其他标准请求头。 - 无会话上下文管理:浏览器访问站点时会自动存储、携带站点下发的Cookie(会话Cookie、验证Cookie等),你的代码使用无状态的单次请求,没有维护Cookie上下文,请求达到一定数量后就会被拦截。
- 请求规律过于机械:固定0.5秒的请求间隔节律性极强,反爬系统很容易识别出非人类操作特征,即使间隔不算短,规律化的请求特征依然会触发拦截规则。
- 缺少动态校验参数:部分站点会在前端生成动态请求校验参数(如CSRF Token、请求签名等),你的请求仅拼接了页面ID,没有携带这些动态生成的合法参数,累计请求后被校验逻辑拦截。
可行解决方法
- 补全合法请求头:从浏览器开发者工具中复制正常访问该页面时的请求头,至少携带
User-Agent、Accept、Accept-Language、Referer等基础头信息,替换requests默认的请求头。示例代码:
headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8", "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8", "Referer": "目标站点的首页地址" } # 请求时传入headers参数 response = requests.get(url, headers=headers)
- 维护会话状态:使用
requests.Session()创建会话对象,自动管理Cookie,模拟浏览器的上下文状态,避免无状态请求被拦截。示例代码:
session = requests.Session() # 首次先请求站点首页,获取初始Cookie session.get(DEFAULT_URL, headers=headers) # 后续所有请求都使用session对象发送 response = session.get(url, headers=headers)
- 随机化请求间隔:把固定间隔改为随机浮动的间隔,模拟人类操作节律,比如每次间隔在0.3到1.5秒之间随机取值。示例代码:
import random time.sleep(random.uniform(0.3, 1.5))
- 增加异常重试机制:遇到403、500、连接超时等异常时,暂停一段时间后重试,重试次数建议设置3-5次,每次重试间隔可逐步递增,避免单次拦截直接终止任务。
- 若站点存在动态校验参数,可以先从当前页面的HTML内容或者接口响应中提取对应的参数,再拼接进下一次请求的参数中,保证请求参数合法。
内容的提问来源于stack exchange,提问作者Ron Keinan
相关产品推荐
相关产品推荐

