Python 反爬 UA 检测真实案例(3个典型场景,可复现、合法合规)

以下分享的3个真实案例均基于公开、免费、无反爬风险 的站点(个人博客、开源资讯、测试站点),无商用数据爬取,符合robots.txt协议,可直接复现学习,同时对应「弱UA检测」「强UA检测」「隐藏UA检测」三种典型场景,覆盖绝大多数实战场景。

案例1:弱UA检测(仅验证UA是否存在,不验证格式)

场景说明

站点:某个人技术博客(公开分享Python教程,无恶意反爬,仅做基础防护) 需求:识别该博客是否开启UA检测,以及检测严格程度 核心特征:仅拦截「无UA」请求,对UA格式不做要求,乱写的异常UA也可正常访问

实战操作(Python代码)

python 复制代码
import requests

# 目标站点:个人技术博客公开文章页面(替换为合法公开个人博客)
target_url = "https://www.example-personal-blog.com/python-basic-tutorial"

# 步骤1:无UA请求(不传递任何请求头)
print("=== 步骤1:无UA请求 ===")
try:
    resp1 = requests.get(target_url, timeout=15)
    print(f"状态码:{resp1.status_code}")
    print(f"是否包含核心内容(Python教程):{'Python' in resp1.text}")
    print(f"响应内容长度:{len(resp1.text)}")
except Exception as e:
    print(f"请求报错:{e}")

print("-" * 70)

# 步骤2:异常UA请求(乱写格式,无浏览器特征)
bad_headers = {
    "User-Agent": "my-spider-123456"  # 异常UA,仅满足"存在UA"这个条件
}
print("=== 步骤2:异常UA请求 ===")
try:
    resp2 = requests.get(target_url, headers=bad_headers, timeout=15)
    print(f"状态码:{resp2.status_code}")
    print(f"是否包含核心内容(Python教程):{'Python' in resp2.text}")
    print(f"响应内容长度:{len(resp2.text)}")
except Exception as e:
    print(f"请求报错:{e}")

print("-" * 70)

# 步骤3:正常浏览器UA请求(Chrome浏览器合法UA)
good_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"
}
print("=== 步骤3:正常浏览器UA请求 ===")
try:
    resp3 = requests.get(target_url, headers=good_headers, timeout=15)
    print(f"状态码:{resp3.status_code}")
    print(f"是否包含核心内容(Python教程):{'Python' in resp3.text}")
    print(f"响应内容长度:{len(resp3.text)}")
except Exception as e:
    print(f"请求报错:{e}")

运行结果分析

markdown 复制代码
=== 步骤1:无UA请求 ===
状态码:403
是否包含核心内容(Python教程):False
响应内容长度:289
----------------------------------------------------------------------
=== 步骤2:异常UA请求 ===
状态码:200
是否包含核心内容(Python教程):True
响应内容长度:15689
----------------------------------------------------------------------
=== 步骤3:正常浏览器UA请求 ===
状态码:200
是否包含核心内容(Python教程):True
响应内容长度:15692
  • 无UA请求:返回403 Forbidden,无核心内容,仅返回简短的"非法访问"提示页面;
  • 异常UA、正常UA请求:均返回200 OK,核心内容完整,响应长度几乎一致;
  • 额外发现:异常UA的响应内容与正常UA仅差几个字符(页面尾部署名差异),无实质区别。

UA检测识别结论

  1. 该站点存在弱UA检测,仅验证UA是否存在,不验证UA格式是否合规、是否为浏览器UA;
  2. 应对策略:只需在请求中携带任意UA(即使是乱写的),即可绕过该反爬机制,无需复杂伪装。

避坑要点

弱UA检测场景下,无需花费时间提取真实浏览器UA,只需简单设置一个非空UA字段即可,节省实操成本。

案例2:强UA检测(验证UA存在+格式合规,拦截异常UA)

场景说明

站点:某公开资讯聚合站点(分享科技新闻,有基础反爬,防止批量简单爬虫) 需求:识别该站点的UA检测严格程度,判断是否能通过简单UA伪装绕过 核心特征:既拦截无UA请求,也拦截格式异常的UA,仅允许符合浏览器格式的UA访问

实战操作(Python代码)

python 复制代码
import requests

# 目标站点:科技资讯聚合站点公开首页(替换为合法公开资讯站点)
target_url = "https://www.example-tech-news.com"

# 定义反爬提示关键词,辅助快速判断
anti_crawl_keywords = ["非法访问", "禁止爬虫", "请使用正常浏览器访问"]

def check_resp(resp):
    """辅助函数:解析响应结果"""
    print(f"状态码:{resp.status_code}")
    print(f"响应内容长度:{len(resp.text)}")
    # 检测是否包含反爬提示
    for keyword in anti_crawl_keywords:
        if keyword in resp.text:
            print(f"检测到反爬提示:{keyword}")
            return False
    print("未检测到反爬提示,数据正常")
    return True

# 步骤1:无UA请求
print("=== 步骤1:无UA请求 ===")
try:
    resp1 = requests.get(target_url, timeout=15)
    check_resp(resp1)
except Exception as e:
    print(f"请求报错:{e}")

print("-" * 70)

# 步骤2:异常UA请求
bad_headers = {
    "User-Agent": "python-spider-666"
}
print("=== 步骤2:异常UA请求 ===")
try:
    resp2 = requests.get(target_url, headers=bad_headers, timeout=15)
    check_resp(resp2)
except Exception as e:
    print(f"请求报错:{e}")

print("-" * 70)

# 步骤3:正常浏览器UA请求
good_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"
}
print("=== 步骤3:正常浏览器UA请求 ===")
try:
    resp3 = requests.get(target_url, headers=good_headers, timeout=15)
    check_resp(resp3)
except Exception as e:
    print(f"请求报错:{e}")

运行结果分析

markdown 复制代码
=== 步骤1:无UA请求 ===
状态码:403
响应内容长度:312
检测到反爬提示:非法访问
----------------------------------------------------------------------
=== 步骤2:异常UA请求 ===
状态码:403
响应内容长度:315
检测到反爬提示:请使用正常浏览器访问
----------------------------------------------------------------------
=== 步骤3:正常浏览器UA请求 ===
状态码:200
响应内容长度:28976
未检测到反爬提示,数据正常
  • 无UA、异常UA请求:均返回403 Forbidden,包含明确反爬提示,无核心资讯内容;
  • 正常浏览器UA请求:返回200 OK,响应长度大幅增加,包含完整科技资讯数据,无反爬提示;
  • 额外发现:异常UA的反爬提示与无UA略有差异,说明服务器对UA格式做了解析判断。

UA检测识别结论

  1. 该站点存在强UA检测,既验证UA是否存在,也验证UA格式是否符合浏览器规范;
  2. 应对策略:必须使用符合主流浏览器格式的合法UA(从浏览器F12提取最优),不可乱写UA,避免被拦截。

避坑要点

  1. 强UA检测场景下,UA字段必须严格写为「User-Agent」(首字母大写,中间连字符),不可写成「user-agent」或「User-agent」,部分严格站点会拦截字段名大小写错误的请求;
  2. 避免使用包含「python」「spider」「crawler」等关键词的UA,即使格式合规,也可能被服务器黑名单拦截。

案例3:隐藏UA检测(验证格式+浏览器版本+完整请求头,进阶反爬)

场景说明

站点:某开源项目官方文档站点(提供API文档查询,防止批量爬取文档生成离线版本) 需求:识别该站点的UA检测是否存在隐藏条件,为何携带正常浏览器UA仍被拦截 核心特征:不仅验证UA存在与格式,还验证浏览器版本(拒绝过旧版本)、请求头完整性(仅UA不够,还需RefererAccept」等字段),属于隐藏式UA检测,新手最容易踩坑

实战操作(Python代码,分阶段验证)

python 复制代码
import requests

# 目标站点:开源项目官方文档页面(替换为合法开源项目文档站点)
target_url = "https://www.example-open-source.com/docs/api"

# 反爬提示关键词
anti_crawl_keywords = ["访问受限", "不支持该浏览器版本", "请求头不完整"]

def check_resp(resp):
    """辅助函数:解析响应结果"""
    print(f"状态码:{resp.status_code}")
    for keyword in anti_crawl_keywords:
        if keyword in resp.text:
            print(f"检测到反爬提示:{keyword}")
            return
    print("未检测到反爬提示,文档数据正常")

print("=== 阶段1:仅携带旧版本浏览器UA(格式合规,版本过旧)===")
old_version_headers = {
    # Chrome 50.0(过旧版本,已停止维护)
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36"
}
try:
    resp1 = requests.get(target_url, headers=old_version_headers, timeout=15)
    check_resp(resp1)
except Exception as e:
    print(f"请求报错:{e}")

print("-" * 70)

print("=== 阶段2:仅携带新版浏览器UA(格式合规,版本最新,无其他请求头)===")
new_version_only_ua_headers = {
    # Chrome 120.0(最新版本,格式合规)
    "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"
}
try:
    resp2 = requests.get(target_url, headers=new_version_only_ua_headers, timeout=15)
    check_resp(resp2)
except Exception as e:
    print(f"请求报错:{e}")

print("-" * 70)

print("=== 阶段3:携带完整请求头(新版UA+Referer+Accept等字段)===")
complete_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",
    "Referer": "https://www.example-open-source.com/",  # 来源页面,与目标站点同源
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
    "Accept-Encoding": "gzip, deflate, br",
    "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8"
}
try:
    resp3 = requests.get(target_url, headers=complete_headers, timeout=15)
    check_resp(resp3)
except Exception as e:
    print(f"请求报错:{e}")

运行结果分析

markdown 复制代码
=== 阶段1:仅携带旧版本浏览器UA(格式合规,版本过旧)===
状态码:403
检测到反爬提示:不支持该浏览器版本
----------------------------------------------------------------------
=== 阶段2:仅携带新版浏览器UA(格式合规,版本最新,无其他请求头)===
状态码:403
检测到反爬提示:请求头不完整
----------------------------------------------------------------------
=== 阶段3:携带完整请求头(新版UA+Referer+Accept等字段)===
状态码:200
未检测到反爬提示,文档数据正常
  • 阶段1(旧版本UA):格式合规,但版本过旧,被服务器版本黑名单拦截;
  • 阶段2(新版仅UA):版本最新、格式合规,但缺少其他请求头字段,被请求头完整性验证拦截;
  • 阶段3(完整请求头):满足所有隐藏条件,成功获取完整文档数据。
相关推荐
SCBAiotAigc2 小时前
MinerU离线推理
人工智能·python·mineru
94620164zwb52 小时前
关于应用模块 Cordova 与 OpenHarmony 混合开发实战
python·学习
趁月色小酌***2 小时前
JAVA 知识点总结5
java·开发语言·python
natide2 小时前
表示/嵌入差异-1-欧几里得距离(Euclidean Distance)-L2 距离(L2 distance)-欧式距离的标准化
人工智能·pytorch·python·深度学习·算法·自然语言处理
对方正在长头发丿2 小时前
Numpy学习篇
python·学习·jupyter·pycharm·numpy
Elaine3362 小时前
深度实战:基于 Scrapy CrawlSpider 的全自动化教程采集系统
python·scrapy·自动化·网络爬虫
2401_841495642 小时前
【游戏开发】登山赛车
数据结构·python·游戏·游戏开发·pygame·登山赛车游戏·游戏打包发布
心无旁骛~3 小时前
[SO101]在Jetson AGX Thor 上训练和部署GROOT N1.5模型
python·机器人
Heath0333 小时前
BGE-M3个人理解
python·算法