Python爬虫请求遭服务器反爬检测,求检测机制及可行方案
服务器检测Python爬虫的常见机制及你的场景分析
从你的描述来看,服务器能精准识别Python请求但放行Charles代理、PowerShell请求,核心是Python请求库的底层网络特征和浏览器/系统原生网络栈存在差异,以下是具体的检测机制:
1. TLS指纹检测(JA3/JA3S)
这是目前最常见的检测手段之一。Python的requests/aiohttp依赖OpenSSL或cryptography库实现TLS握手,其Cipher Suite(加密套件)顺序、TLS扩展字段、版本协商逻辑和浏览器/Windows系统栈完全不同。服务器通过JA3指纹(客户端TLS握手特征)可以直接识别出这是Python发出的请求。
- 你用Charles代理时,Charles会用自己的TLS栈(模拟浏览器特征)和服务器握手,相当于替Python“换了指纹”,所以能通过。
- PowerShell的
Invoke-WebRequest用的是Windows原生的Schannel TLS栈,和Chrome/Edge等浏览器的指纹高度重合,因此能通过;而bash的curl默认用OpenSSL,和Python的指纹类似,所以被拦截。
2. TCP层特征差异
Python请求库的底层TCP实现(如urllib3的socket逻辑)和浏览器/系统网络栈存在细节差异:
- TCP握手时的窗口大小、MSS(最大分段大小)、选项字段(如Timestamp)设置不同;
- 请求头的发送时序:Python会一次性发送所有请求头,而浏览器会分批次发送,或者有微小的间隔;
- 数据包的分片策略差异。
这些细微特征被服务器的WAF(Web应用防火墙)捕捉后,会判定为非人类请求。
3. 请求头的隐藏细节
即使你替换了User-Agent,还有很多容易忽略的头特征:
- 头的顺序:浏览器发送请求头的顺序是固定的(比如先Host、再User-Agent、再Accept等),但
requests默认会对headers按字母排序发送,服务器会检查这个顺序; - Accept-Encoding的内容:Python默认发送
gzip, deflate,而浏览器通常会加上br(Brotli压缩); - 隐藏的默认头:
requests会自动添加Connection: keep-alive、Accept: */*等头,这些和浏览器的默认值可能不一致; - Cookie的格式:如果涉及Cookie,Python处理的Cookie格式可能和浏览器有差异,比如缺少某些属性。
4. 其他可能的检测点
- HTTP/2协议支持:部分服务器会优先检查HTTP/2的请求特征,Python的
requests默认用HTTP/1.1,而浏览器大多用HTTP/2; - 请求体的编码方式:如果发送POST请求,Python的编码逻辑和浏览器可能不同,比如表单数据的分隔符、编码格式;
- DNS解析特征:Python的DNS解析逻辑和浏览器/系统原生解析不同,服务器可能通过DNS请求的来源判断。
针对性的解决思路
- 修正TLS指纹:使用支持自定义JA3指纹的库,比如
httpx结合第三方指纹修改工具,或者直接用playwright/pyppeteer这类模拟真实浏览器的工具(完全复用浏览器的TLS栈); - 严格复刻浏览器请求头:用浏览器开发者工具复制完整请求头(包括顺序),在Python中用
OrderedDict(或httpx的headers参数,支持保留顺序)发送; - 使用系统原生网络栈:比如在Windows上用
ctypes调用WinHTTP接口,或者用requests通过系统代理转发(类似Charles的方式); - 调整TCP参数:通过
socket模块自定义TCP的窗口大小、MSS等参数,不过这个难度较高。
内容的提问来源于stack exchange,提问作者hrhhr
相关产品推荐
相关产品推荐

