以下分享的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检测识别结论
- 该站点存在弱UA检测,仅验证UA是否存在,不验证UA格式是否合规、是否为浏览器UA;
- 应对策略:只需在请求中携带任意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检测识别结论
- 该站点存在强UA检测,既验证UA是否存在,也验证UA格式是否符合浏览器规范;
- 应对策略:必须使用符合主流浏览器格式的合法UA(从浏览器F12提取最优),不可乱写UA,避免被拦截。
避坑要点
- 强UA检测场景下,UA字段必须严格写为「User-Agent」(首字母大写,中间连字符),不可写成「user-agent」或「User-agent」,部分严格站点会拦截字段名大小写错误的请求;
- 避免使用包含「python」「spider」「crawler」等关键词的UA,即使格式合规,也可能被服务器黑名单拦截。
案例3:隐藏UA检测(验证格式+浏览器版本+完整请求头,进阶反爬)
场景说明
站点:某开源项目官方文档站点(提供API文档查询,防止批量爬取文档生成离线版本) 需求:识别该站点的UA检测是否存在隐藏条件,为何携带正常浏览器UA仍被拦截 核心特征:不仅验证UA存在与格式,还验证浏览器版本(拒绝过旧版本)、请求头完整性(仅UA不够,还需Referer「Accept」等字段),属于隐藏式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(完整请求头):满足所有隐藏条件,成功获取完整文档数据。