Python 反爬 UA 检测核心识别技巧(实战干货,可直接落地)

89 阅读7分钟

UA 检测作为最基础、最常见的反爬手段,识别的核心是**“找差异、验合规、判结果”**,以下分享一系列实战性极强的技巧,均来自爬虫落地过程中的真实经验总结,避开理论空谈,直接对接实操场景。

一、 前期准备:先搞定“有效UA”,避免从源头踩坑

  1. 浏览器F12精准提取合法UA(首选,最可靠) 这是获取有效UA的核心方法,避免手动编造或使用过时UA被拦截:

    • 打开Chrome/Edge浏览器,访问目标站点(确保正常访问);
    • F12打开开发者工具,切换到「Network」面板,勾选「Preserve log」(保留日志);
    • 刷新页面,找到第一个GET请求(通常是目标站点的文档请求,Type为「document」);
    • 下拉找到「Request Headers」,复制User-Agent对应的完整字符串(从头到尾完整复制,避免遗漏字符);
    • 直接粘贴到Python请求头字典中,不做任何修改,这是通过UA检测的“黄金标准”。
  2. 避开requests库默认UA(新手必避坑) requests库在不手动设置UA时,会默认传递python-requests/xx.xx.xx(xx为版本号),这类UA会被绝大多数开启UA检测的网站直接拦截,因此任何爬虫请求,都必须手动覆盖默认UA,不抱有任何侥幸心理。

  3. UA格式快速验证技巧 合法浏览器UA都有固定结构(操作系统+渲染引擎+浏览器版本+兼容内核),若拿到的UA不包含这些要素,大概率无效:

    • 必备要素:Windows NT/ macOS(操作系统)、AppleWebKit(渲染引擎)、Chrome/Edge/Safari(浏览器);
    • 排除要素:包含pythonspidercrawlerbot等关键词的UA,几乎100%会被拦截。

二、 核心识别:三步对比法,精准判定是否存在UA检测

这是识别UA检测的“万能方法”,通过发送三种不同UA的请求,对比响应结果,即可快速得出结论,无任何技术门槛。

步骤1:发送“无UA”请求(仅传递空请求头或不传递请求头)

  • 操作:Python中不设置headers参数,直接发送requests.get(url)
  • 观察结果:记录响应状态码(403/400/200)、响应内容长度、是否包含“非法访问”提示;
  • 核心意义:验证网站是否强制要求携带UA,无UA直接拦截是UA检测的最典型特征。

步骤2:发送“异常UA”请求(传递格式无效、乱写的UA)

  • 操作:设置明显不符合浏览器格式的UA,如headers={"User-Agent": "123456"}headers={"User-Agent": "my-spider"}
  • 观察结果:对比与“无UA”请求的结果是否一致(是否均返回403、是否均无有效内容);
  • 核心意义:验证网站是否不仅要求“存在UA”,还要求“UA格式合规”,这是区分“弱UA检测”和“强UA检测”的关键。

步骤3:发送“正常浏览器UA”请求(传递步骤1提取的合法UA)

  • 操作:设置完整的浏览器UA,如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"}
  • 观察结果:记录是否返回200、是否包含完整的目标页面数据;
  • 核心意义:通过与前两步结果对比,完成最终判定。

判定逻辑(直接套用)

  1. 若步骤1、步骤2均返回403/400,步骤3返回200且数据完整 → 判定存在强UA检测(既验证UA存在,又验证格式合规);
  2. 若步骤1返回403,步骤2、步骤3均返回200且数据完整 → 判定存在弱UA检测(仅验证UA是否存在,不验证格式);
  3. 若三步均返回200且数据完整 → 判定未开启UA检测
  4. 补充:若三步均返回200,但步骤1、2的响应内容是“访问受限”提示,步骤3是正常数据 → 仍判定存在UA检测(部分网站不返回错误状态码,仅返回错误内容)。

三、 细节优化:提升UA检测识别准确率的辅助技巧

  1. 响应内容优先于状态码(关键避坑) 很多网站为了隐藏反爬机制,不会返回403/400等错误状态码,而是返回200,但响应内容是空白页面、“非法访问”提示页或跳转页面。因此,识别时不能只看状态码,必须解析响应内容的核心关键词(如“登录”、“禁止”、“非法”、“不支持”),这是提升准确率的核心。

  2. 关键词检索法,快速辅助判定 编写简单的关键词匹配逻辑,自动筛选响应内容中的反爬提示,避免人工逐一查看:

    # 关键词检索辅助判定UA检测
    import requests
    
    url = "https://www.example.com"
    good_headers = {"User-Agent": "合法浏览器UA"}
    bad_headers = {"User-Agent": "123456"}
    
    # 定义反爬提示关键词列表
    anti_crawl_keywords = ["非法访问", "禁止", "不支持", "请使用浏览器", "Login", "Forbidden"]
    
    def check_ua_detection(headers):
        resp = requests.get(url, headers=headers, timeout=10)
        # 遍历关键词,判断是否包含反爬提示
        for keyword in anti_crawl_keywords:
            if keyword in resp.text:
                return True, f"检测到反爬提示:{keyword}"
        return False, "未检测到反爬提示,数据正常"
    
    # 验证异常UA
    is_anti, msg = check_ua_detection(bad_headers)
    print(f"异常UA请求结果:{msg}")
    
  3. 排除其他反爬干扰,避免误判 识别UA检测时,需先排除IP封禁、Cookie验证等其他反爬的干扰,避免将其他反爬误判为UA检测:

    • 若更换IP(如本地WiFi→手机热点)后,前两步请求从403变为200 → 大概率是IP封禁,而非UA检测;
    • 若携带有效Cookie后,前两步请求从403变为200 → 大概率是Cookie验证,而非UA检测。
  4. 验证UA字段的大小写敏感性 部分严格的网站会验证请求头中User-Agent字段的大小写,若写成user-agentUser-agent,可能会被拦截。因此,请求头中UA字段的键必须严格写为「User-Agent」(首字母大写,其余小写,中间连字符连接),避免因字段名错误导致误判。

四、 进阶技巧:识别隐藏的UA检测(针对高难度站点)

  1. UA版本有效性验证 部分网站不仅验证UA格式,还会验证浏览器版本、操作系统版本,即使格式合规,若使用过旧的UA(如Chrome 50.0),也会被拦截。此时可通过更换不同版本的浏览器UA(如Chrome 119、Chrome 120)进行对比,若部分版本通过、部分版本被拦截,说明存在隐藏的UA版本检测。

  2. 完整请求头伪装,避免UA“孤立” 部分网站会验证请求头的完整性,仅伪装UA,而缺少RefererAcceptAccept-Encoding等字段,也会被拦截,导致误判为UA检测失效。此时需将浏览器中的完整请求头(除Cookie外)全部复制到Python请求中,再进行验证,避免因请求头不完整导致的识别误差。

  3. 批量UA池验证,快速筛选有效UA 对于不确定UA有效性的场景,可搭建简易UA池,通过循环批量发送请求,筛选出能通过UA检测的有效UA,同时验证网站的UA检测严格程度:

    # 简易UA池批量验证
    import requests
    
    url = "https://www.example.com"
    # 构建UA池(包含不同浏览器、不同版本的合法UA)
    ua_pool = [
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Edge/120.0.0.0 Safari/537.36",
        "Mozilla/5.0 (Macintosh; Intel Mac OS X 14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
    ]
    
    for ua in ua_pool:
        headers = {"User-Agent": ua}
        try:
            resp = requests.get(url, headers=headers, timeout=10)
            if "核心内容关键词" in resp.text:
                print(f"UA有效:{ua[:50]}...")
            else:
                print(f"UA无效:{ua[:50]}...")
        except Exception as e:
            print(f"UA验证失败:{ua[:50]}... 报错:{e}")