分享页面
技术分享 / Python requests UA 配置:4 类常见问题与修正

Python requests UA 配置:4 类常见问题与修正

技术分享

做数据采集时,requests 库的 User-Agent 配置看似是最简单的一步——往 headers 字典里塞一个浏览器 UA 字符串就完事了。但实际跑起来,很多人会发现:明明 UA 设了,目标站点还是返回 403;或者跑了没几轮就被限制访问;又或者同一套代码换台机器结果不一样。

问题往往不在 UA 字符串本身,而在 UA 与请求头其他字段的协同、UA 的轮换策略、以及 UA 与底层连接指纹之间的关系。下面拆 4 类最高频的问题,逐个给修正方案。

UA 字符串与请求头其他字段不一致

这是最容易被忽略的问题。很多教程只教你设 User-Agent,但浏览器发请求时,Accept、Accept-Language、Accept-Encoding、sec-ch-ua 等字段会跟着一起走。如果 UA 声称是 Chrome 120,但请求头里 Accept-Language 缺失、Accept 还停留在 */*,目标站点的风控规则很容易判定这不是真实浏览器行为。

典型场景:电商选品采集,目标页面是商品详情页。代码里只设了 UA,没带其他请求头,采集几十条后开始返回验证页面。

修正方法:不要只设 UA,把整套浏览器请求头一起带上。核心字段包括:

import 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",
    "Accept-Encoding": "gzip, deflate, br",
    "Connection": "keep-alive",
    "Upgrade-Insecure-Requests": "1",
}

resp = requests.get("https://example.com/product/123", headers=headers)

关键点:这些字段之间要保持逻辑一致。如果 UA 声称是 Chrome,sec-ch-ua 系列字段也要对应;如果 UA 是移动端浏览器,Accept 里就不该出现 application/xhtml+xml 这种桌面端特征。

单一固定 UA 反复使用

第二个常见问题:写好一个 UA 字符串,然后所有请求、所有时间都用同一个。这在低频场景下可能没问题,但一旦采集量上去——比如舆情监测场景下要同时抓几十个站点的数据——同一个 UA 在短时间内发起大量请求,行为特征非常明显。

很多站点的访问频率控制不仅看 IP,也会看 UA+IP 的组合。同一个 UA 从同一个出口 IP 发起 500 次请求,比 10 个不同 UA 轮换发 500 次请求更容易触发限制。

修正方法:建一个 UA 池,每次请求随机轮换。基础写法:

import random

ua_pool = [
    # Chrome Windows
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
    # Chrome macOS
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
    # Firefox Windows
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0",
    # Edge Windows
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0",
    # Safari macOS
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.2 Safari/605.1.15",
]

headers = {
    "User-Agent": random.choice(ua_pool),
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
    "Accept-Language": "zh-CN,zh;q=0.9",
}

resp = requests.get(url, headers=headers)

但要注意:轮换 UA 时,对应的请求头也应该跟着 UA 走。如果这次选了 Firefox 的 UA,Accept-Encoding 里出现 br 就不太合理(Firefox 支持 br,但格式细节和 Chrome 有差异)。实际操作中,更稳妥的做法是把 UA 和它配套的请求头打包成一组,轮换时整组替换,而不是只换 UA 字符串。

UA 轮换无序导致行为特征异常

第三个问题藏得更深。有了 UA 池、开始轮换了,但轮换方式是 random.choice()——纯随机。表面上看每次请求 UA 不同,但如果短时间内的请求序列是:Chrome → Firefox → Safari → Chrome → Edge → Firefox,这个序列本身就是异常信号。

真实用户不会在 2 秒内用 5 个不同浏览器访问同一个网站。纯随机轮换在低频时有效,在高频采集时反而暴露了自动化特征。

修正方法:给轮换加一层策略控制。核心思路是让 UA 在一段时间内保持稳定,定期切换而非逐请求切换:

import random
import time

class UARotator:
    def __init__(self, ua_pool, switch_interval=50):
        self.ua_pool = ua_pool
        self.switch_interval = switch_interval
        self.current_ua = random.choice(ua_pool)
        self.request_count = 0

    def get_ua(self):
        self.request_count += 1
        if self.request_count >= self.switch_interval:
            self.current_ua = random.choice(self.ua_pool)
            self.request_count = 0
        return self.current_ua

rotator = UARotator(ua_pool, switch_interval=30)

# 每 30 次请求换一次 UA,而不是每次都换
for url in url_list:
    headers = {"User-Agent": rotator.get_ua()}
    resp = requests.get(url, headers=headers)
    time.sleep(random.uniform(1.0, 3.0))

这种做法模拟的是”一个用户用浏览器访问了 30 个页面,然后换了台设备继续”的行为模式,比纯随机更像真人。配合合理的请求间隔(1-3 秒随机),整体行为特征会自然很多。

忽略 UA 与底层连接指纹的协同

最后一个问题最隐蔽。就算 UA 完美、请求头完整、轮换策略合理,有些站点还是会识别出这是脚本。原因是:requests 库底层使用 urllib3,它的 TLS 握手指纹(JA3 指纹)和真实浏览器不同。目标站点如果用 TLS 指纹检测,光改 UA 字符串是没用的——UA 说自己是 Chrome,但 TLS 握手特征暴露了 urllib3。

这个问题的体感:换了 UA、换了 IP,访问还是被挡,而且用浏览器手动打开同一页面完全正常。

修正方法分两步:

第一步,确认是不是 TLS 指纹问题。用浏览器和 requests 分别请求同一 URL,对比返回状态。如果浏览器 200、requests 403,且 UA 和请求头都对齐过,基本可以判断是连接层面的问题。

第二步,换用 TLS 指纹更接近浏览器的 HTTP 客户端。最直接的方案是改用 curl_cffi 库,它的 TLS 握手指纹可以模拟 Chrome 或 Firefox:

from curl_cffi import requests as cffi_requests

# impersonate 参数模拟 Chrome 的 TLS 指纹
resp = cffi_requests.get(
    "https://example.com/data",
    impersonate="chrome120",
    headers=headers,
)

如果不想换库,也可以用 requests + requests-toolbelt 配合自定义 TLS 配置,但效果不如 curl_cffi 直接。需要注意的是,换库之后 UA 和请求头仍然要保持一致——TLS 指纹解决了连接层的问题,应用层的请求头一致性仍然不能丢。

小结

UA 配置不是填一个字符串,而是一套需要多层协同的工程:

  • UA 要和请求头其他字段保持逻辑一致,不能只设 UA 不设 Accept / Accept-Language
  • 高频采集必须建 UA 池轮换,但轮换要有策略,不能纯随机
  • 底层 TLS 指纹是 UA 之外的第二道坎,requests 原生指纹和浏览器不同,必要时换用 TLS 模拟能力更强的客户端

把这四层理清,requests 的 UA 配置才真正算”配好了”。

常见问题

requests 设置了 UA 还是返回 403,怎么排查?

按三层顺序排查:先检查 UA 是否带了配套请求头(Accept、Accept-Language 等),只设 UA 不设其他字段是最高频原因;再确认 UA 字符串是否过期,Chrome 大版本每 4-6 周迭代一次,用过老的版本号会被部分站点风控规则判定为异常;最后用浏览器手动访问同一 URL,如果浏览器也 403,说明是 IP 层面的问题而非 UA。

UA 池需要多大?多少个够用?

5-10 个不同浏览器+操作系统组合足够应对大多数场景。池太小(1-2 个)轮换没意义,池太大(50+)维护成本高且多数 UA 实际行为特征接近,收益递减。比池大小更重要的是轮换策略和请求间隔——30 个 UA 纯随机每秒切一次,不如 5 个 UA 每 30 次请求切一次。

curl_cffi 和 requests 能混用吗?

可以。常见做法是 requests 打底处理大部分请求,遇到 TLS 指纹检测的站点时切换到 curl_cffi。两者 API 接口接近,迁移成本低。需要注意的是 curl_cffi 的 session 管理和 requests 略有差异,建议封装一层统一接口,避免在业务代码里到处做条件判断。

UA 配置好后还需要配代理吗?

两者解决的是不同层面的问题。UA 和请求头管的是应用层身份,代理管的是网络层出口。高频采集场景下,UA 池+代理通常是配合使用的——单 IP 配多 UA 可以分散应用层特征,但 IP 层面仍然集中在同一出口,访问频率控制还是会生效。具体是否需要代理取决于目标站点的限制策略和采集量级。

推荐阅读
手把手教你配置 SOCKS5 代理,新手小白也能上手!

当谈到代理技术时,SOCKS5代理凭借其高兼容性、快速的传输性能和广泛的适用场景,成为了许多用户与开发者的首选。不管你是想提升爬虫数据采集的成功率,还是优化跨区域网络连接,都需要配置SOCKS5代理。今天,我们将带你从零开始学习SOCKS5代理的配置方法。不论你是小白用户第一次接触代理,还是需要优化...

2025-01-23
SOCKS5代理IP
代理http的是什么,有什么用

在数据驱动的世界里,无论是企业还是个人开发者,都离不开数据采集。采集数据信息不仅帮助我们了解市场动态,更支撑了大数据分析、机器学习等前沿技术的发展。然而,随着数据量的不断增大以及网络环境的复杂性,如何保证数据采集的效率和稳定性已经成为了一项不可忽视的挑战。而代理HTTP在当中扮演了重要的角色。 ...

2024-08-02
HTTP代理
国外代理ip节点哪里购买?高质量海外代理购买方法

您是否需要一篇深入且实用的指南来解答“国外代理IP节点哪里购买”的问题?网络时代,各类用户对国外代理IP的需求逐渐增加,无论是开发者、数据职业者,还是企业级用户,选择高质量的海外代理IP至关重要。那么,如何才能购买到适合自身需求的高质量代理IP呢?这篇文章将从购买渠道、选择要点和使用方法等方面为您详...

2025-07-24
国外代理IP
3分钟了解:静态IP和动态IP的区别具体在哪里?

如果你是一名开发者、网络管理员,或者是对网络技术感兴趣的小伙伴,想必你时常会听到“静态IP”和“动态IP”这两个名词。它们在互联网世界里扮演着重要角色,却存在显著差异。在日常工作的不同场景中,如何正确选择两者,才能更高效地解决实际问题? 本文将带你在3分钟内轻松搞懂静态IP和动态IP的主要区别...

2025-01-16
动态代理IP 静态代理IP
IP 隧道深度解析:原理、优势与实战选型

很多团队第一次接触“IP 隧道”(也常被称作“隧道代理”)时,会把它与传统网络中的 GRE、IPsec 等隧道概念混为一谈。二者确有渊源,却服务于不同目标:网络隧道更偏向专网互联与封装转发;而代理领域的 IP 隧道,则是通过一个稳定的入口节点,把后端海量出口 IP 的调度、轮换与质量控制“藏在门后”...

2025-09-30
http隧道代理 隧道代理IP
深入解析动态ip:什么是动态IP?动态IP与静态IP对比

在日常生活和企业应用中,IP地址是每台设备接入互联网的“身份标识”。大多数人每天使用的其实并不是固定不变的地址,而是运营商临时分配的 动态IP。与静态IP相比,动态IP更普遍、更经济,也更适合普通用户和一些大规模任务。本文将深入解析动态IP的特征及应用场景。 1 什么是动态IP 动态I...

2025-09-23
静态代理IP 动态代理IP
扫码添加专属客服
扫码关注公众号