导读:本期聚焦于白鲨创作的《Python爬虫如何提高抓取成功率?多策略混合验证请求头合法性详解》,敬请观看详情。网页抓取频繁返回403或验证页面,往往不是IP被封,而是请求头暴露了爬虫身份。本文从User-Agent轮换、Header完整性校验、TLS指纹与请求顺序模拟等多个角度,讲解如何构造接近真实浏览器的合法请求头,并通过多策略混合验证的方式动态检测请求是否被识别。文中提供可直接运行的Python代码示例,涵盖fake_useragent库的使用、headers字典的构建规范、会话保持技巧以及请求失败后的自动重试与降级方案,帮助爬虫在合规前提下大幅提升抓取成功率。

不少写爬虫的朋友遇到过同一个问题:代码在浏览器里能正常访问的页面,用requests一请求就返回403或者一串验证码页面。排查半天IP也没问题,换代理也无效,真正的元凶往往藏在请求头里。服务器端的反爬系统会检查请求头各个字段的合法性,任何一处不符合浏览器特征,请求都会被拦下。本文围绕请求头合法性这一核心,介绍一套多策略混合验证的实战方案。

Python爬虫如何提高抓取成功率?多策略混合验证请求头合法性详解

一、为什么你的请求头会被反爬系统识破

反爬系统判断一个请求是否来自真实浏览器,通常不是只看某一个字段,而是做交叉验证。最常见的问题有三个:User-Agent写死成一个老版本、Header字段残缺不全、字段之间的顺序和取值互相矛盾。

举个例子,很多教程给的示例代码里User-Agent写的是Chrome 40的版本字符串,而请求头里却带着sec-ch-ua这类只有Chrome 90以上才会发送的字段,两者明显冲突。再比如声明自己是移动端浏览器,却请求了桌面端的页面资源,这种矛盾在风控系统眼里非常扎眼。

此外,requests默认的请求行为也和浏览器不同。浏览器访问页面时总会携带Accept、Accept-Language、Referer等一整套字段,而requests默认只发送极少的几个头,这种请求一到达服务器就会被标记为可疑流量。

二、构建完整的请求头并实现UA轮换

第一步是把请求头补全。一个合格的请求头至少要包含User-Agent、Accept、Accept-Language、Connection这几个基础字段。下面是一套可用的模板代码,配合随机UA实现轮换:

import requests
import random
from fake_useragent import UserAgent

ua = UserAgent()

def build_headers(referer=None):
    agent = ua.chrome  # 只使用Chrome的UA,保证特征一致
    headers = {
        "User-Agent": agent,
        "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",
        "Cache-Control": "no-cache",
        "Pragma": "no-cache",
    }
    if referer:
        headers["Referer"] = referer
    return headers

session = requests.Session()
resp = session.get("https://ipipp.com/news/list", headers=build_headers())
print(resp.status_code)

这里有两个细节值得注意。第一,UA轮换不要用所有浏览器的UA随机混用,同一会话内应保持同一身份,最好固定一个浏览器家族。第二,使用Session对象可以让服务器set-cookie返回的Cookie在后续请求中自动携带,很多网站的第一步校验就是发放Cookie然后检查你是否带回来,跳过这一步会直接触发二次验证。

Referer的设置同样重要。直接从首页点进详情页的请求一定会带Referer,如果你的请求光秃秃地什么都没有,很容易被判定为脚本行为。正确做法是先请求列表页,再把列表页地址作为Referer去请求详情页。

三、多策略混合验证:请求前自检,请求后探测

光把请求头写好还不够,更稳妥的做法是建立一套验证机制,在请求发出前对请求头做合法性自检,在响应返回后判断是否被拦截,两者结合形成闭环。

请求前的自检包括:UA版本号与sec-ch-ua字段是否匹配、必填字段是否齐全、UA与Accept-Language的语言地区是否一致。可以写一个校验函数:

REQUIRED_HEADERS = {"User-Agent", "Accept", "Accept-Language"}

def validate_headers(headers):
    # 检查必填字段
    missing = REQUIRED_HEADERS - set(headers.keys())
    if missing:
        raise ValueError(f"缺少必要请求头: {missing}")
    # 检查UA与客户端提示字段的一致性
    ua = headers.get("User-Agent", "")
    sec_ch = headers.get("sec-ch-ua", "")
    if "Chrome/120" in ua and "Chromium" not in sec_ch:
        raise ValueError("UA与sec-ch-ua字段版本不匹配")
    return True

请求后的探测则要识别伪装得很像正常响应的拦截页。有些网站被封时不返回403,而是返回200加一个验证码页面,只看状态码会误判成功。可靠的判断依据包括:响应体长度异常偏短、内容中包含滑块或验证码关键词、正文结构与历史响应差异过大。一旦探测到被拦截,就触发降级策略:更换UA、补充Cookie、降低请求频率后重试。

def is_blocked(resp):
    if resp.status_code in (403, 412, 461):
        return True
    text = resp.text
    trap_words = ["验证码", "滑动验证", "访问异常", "captcha"]
    if any(w in text for w in trap_words):
        return True
    if len(resp.content) < 500 and resp.status_code == 200:
        return True  # 页面短得反常,大概率是拦截页
    return False

def fetch_with_retry(session, url, max_retry=3):
    for i in range(max_retry):
        headers = build_headers(referer="https://ipipp.com/")
        resp = session.get(url, headers=headers, timeout=10)
        if not is_blocked(resp):
            return resp
        time.sleep(random.uniform(3, 6))  # 被拦截后降温再试
    return None

四、进阶:TLS指纹与HTTP/2层面的伪装

当对方站点反爬等级较高时,仅靠请求头已经不够。服务器还能通过TLS握手指纹识别客户端:requests基于urllib3的TLS特征与Chrome差异明显,请求头再完美也会露馅。这时可以改用基于浏览器内核或专门模拟浏览器TLS的库。

常用的方案有两类。一类是curl_cffi,它内置了Chrome的TLS指纹模拟,用法几乎和requests一致:

from curl_cffi import requests as creq

# impersonate参数指定模拟Chrome浏览器的TLS与HTTP/2指纹
resp = creq.get("https://ipipp.com/data", impersonate="chrome")
print(resp.status_code)

另一类是直接用Playwright驱动真实浏览器,指纹层面几乎无懈可击,代价是资源消耗大、速度慢。工程实践中的合理分工是:普通页面用requests加完整请求头处理,遇到强校验的接口用curl_cffi,只有涉及复杂JS计算或滑块验证时才动用Playwright,形成三级降级结构。

最后要强调,抓取成功率与请求频率是一对矛盾体。无论请求头做得多逼真,短时间高频访问任何网站都会触发风控。在多策略混合验证的基础上叠加随机延时、并发控制和遵守robots协议,才能让爬虫长期稳定地运行下去。

Python爬虫请求头反爬虫修改时间:2026-09-10 00:02:42

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/0910/53679.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。