浏览器里配代理IP打开网站没问题,复制同一个代理到Python requests里——403或者验证码。不是代理IP变了,是浏览器和代码的请求特征完全不同。
浏览器能过、代码被拦的四个原因
User-Agent:浏览器自动带UA(Chrome/Firefox完整特征)。Python requests默认UA是”python-requests/x.x.x”——一看就是脚本。改UA是最基本的修复:headers={“User-Agent”: “Mozilla/5.0 …”}。
TLS指纹:浏览器有真实的TLS握手特征。Python requests用的是urllib3+OpenSSL的固定TLS指纹——和浏览器完全不同。网站通过JA3指纹识别这是Python。升级到tls_client或curl_impersonate(参考第44篇ID 13599)。
JavaScript执行:浏览器会执行网页里的JS——网站可能用JS做二次验证。Python requests完全不执行JS→验证失败。升级到Selenium/Playwright用真实浏览器。
请求头顺序和缺失:浏览器发送的请求头有特定的顺序和组合(Accept、Accept-Language、Sec-Fetch等)。代码默认请求头只有少数几个→和浏览器差异明显。
天行IP(邀请码 blsj,月付6元起)的节点本身没问题——区别在于用浏览器访问还是用代码访问。
最少改动能让代码”像浏览器”
改User-Agent为真实的Chrome UA、补全Accept/Accept-Language/Accept-Encoding等标准请求头、用requests.Session保持Cookie和连接、加上Referer模拟是从搜索引擎或站内页面跳过来的。这四点改完后通过率能提升一截,但不如直接上Selenium+住宅IP效果彻底。
常见问题
改了UA和请求头还是被拦?
JA3指纹和JS执行两个维度没覆盖。改UA只是改了HTTP层,TLS层的指纹不变。上tls_client库替换底层TLS实现。
为什么同一个请求浏览器返回200、代码返回403?
403=服务器拒绝访问——不是因为IP被封(被封通常是连不上),是请求被识别为非浏览器。IP没问题,请求特征有问题。






