Python requests请求返回403但浏览器可正常访问 登录自动化求助
403问题核心原因
该站点部署了多维度的反爬识别机制,只要校验到请求的客户端特征和真实浏览器存在差异,就会直接返回403状态码,不返回任何页面内容。这类拦截和代码逻辑无关,无论是requests还是curl,因为默认的客户端特征会被风控规则识别为非浏览器请求,所以才会出现浏览器正常访问、命令行请求全被拦截的现象。
可落地的排查与解决方向
- 替换所有默认请求头,对齐真实浏览器的请求特征
原生requests默认在请求头中携带User-Agent: python-requests/版本号标识,这个字段会被目标站点的风控规则直接拉黑,哪怕其他参数完全匹配,只要携带这个标识就会被拦截。需要将请求头替换为和真实浏览器完全一致的内容,参考基础配置:
不要添加多余的自定义请求头,否则反而会被识别为异常请求。headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.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.8", "Connection": "keep-alive", "Upgrade-Insecure-Requests": "1" } - 使用会话对象维持连续的请求状态
该站点的登录页需要校验临时访客Cookie和CSRF Token:正常用户的访问路径是先GET登录页,由服务器下发临时会话Cookie、生成页面内的CSRF校验参数,后续提交登录请求时需要携带这些值才会通过校验。如果每次请求都新建独立连接、不保留之前获取的Cookie,哪怕请求头完全匹配,也会被风控拦截。需要用会话对象承接所有请求,不要每次直接调用独立的GET/POST方法。 - 适配TLS指纹类拦截规则
就算把所有请求头调整到和浏览器完全一致,原生requests库的TLS握手参数(SSL层的客户端指纹)和Chrome、Edge等真实浏览器仍存在明显差异,这类中大型站点现在会直接抓取该特征做拦截:只要检测到TLS指纹匹配Python requests的特征,不管请求头是什么都会返回403。这种场景下可以使用支持模拟Chrome TLS指纹的HTTP库替换原生requests,使用逻辑和原生requests几乎一致,不需要大幅改动现有代码就能绕过这类拦截。 - 排查IP本身的风险
如果当前使用的网络出口IP(如公共代理、机房IP)已经被目标站点加入风控黑名单,哪怕所有客户端特征都匹配,依然会返回403。可以切换到本地家用宽带网络测试,如果能正常获取页面,就说明之前使用的IP被风控拦截了。
调整后的参考代码
# 先执行pip install curl_cffi安装依赖库,该库会自动模拟真实浏览器的TLS指纹 from curl_cffi import requests from bs4 import BeautifulSoup url = "https://ais.usvisa-info.com/en-am/niv/users/sign_in" # 创建会话对象自动维持cookie状态 session = requests.Session() # 配置和真实浏览器一致的请求头 headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.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.8", "Connection": "keep-alive", "Upgrade-Insecure-Requests": "1" } # 发起GET请求,指定模拟Chrome125版本的客户端特征,绕过TLS检测 resp = session.get(url, headers=headers, impersonate="chrome125") soup = BeautifulSoup(resp.text, 'lxml') # 写入文件时指定编码,避免中文乱码 with open("usvisa.html", "w", encoding="utf-8") as f: f.write(soup.prettify())
注意:不要使用爬虫工具生成的过度冗长的请求头列表,部分站点会检测请求头的顺序和数量,多余的参数反而会触发异常。
内容的提问来源于stack exchange,提问作者artin ghasivand
相关产品推荐
相关产品推荐

