1. 项目概述当爬虫遇上“铜墙铁壁”干爬虫这行久了你就会发现现在的互联网环境跟几年前完全是两个世界。以前可能一个简单的requests.get()加上User-Agent就能畅通无阻现在呢你精心构造的请求发出去换来的常常是403 Forbidden、429 Too Many Requests或者更让人头疼的unexpected status 502 bad gateway。这背后是网站防御系统的一次全面升级它们不再仅仅看你“是谁”IP更开始审视你“像不像一个真人”。这就是我们今天要深入探讨的核心HTTP请求伪装。这不仅仅是为了绕过小红书、抖音这类内容平台的反爬机制更是现代数据采集工程师必须掌握的核心生存技能。从最基本的请求头伪装到复杂的浏览器指纹模拟每一步都是在与风控系统进行一场精密的“猫鼠游戏”。这篇文章我将结合我这些年踩过的坑和实战经验为你拆解从入门到进阶的完整伪装链条让你手里的爬虫不再是那个一眼就被识破的“机器人”。2. 核心对抗思路从请求头到浏览器指纹的全面伪装想要成功获取数据你得先理解对方是怎么发现你的。现代反爬策略是一个立体的防御体系我们的伪装也必须是多维度的。2.1 反爬机制的演进与我们的应对策略早期的反爬相对简单主要依赖频率限制和IP封禁。你的爬虫如果请求太快或者用一个IP发起大量连接很快就会被关进“小黑屋”。所以初代的对抗方案集中在代理IP池和请求延迟上。但这只是第一层。随着技术发展风控系统开始检查你的HTTP请求头。一个使用默认Pythonrequests库User-Agent的请求就像举着“我是机器人”的牌子在门口晃悠。于是我们学会了伪造完整的请求头包括Accept、Accept-Language、Referer、Connection等让请求看起来像是来自一个真实的浏览器。但这还不够。近年来以小红书、抖音为代表的平台以及众多金融、电商网站已经将防御重点转向了浏览器指纹。什么是浏览器指纹你可以把它理解为你浏览器设备的“数字身份证”。它通过收集浏览器暴露的众多信息来生成一个近乎唯一的标识符这些信息包括Canvas指纹浏览器绘制Canvas图像时因硬件、驱动、操作系统的细微差异会产生不同的像素点。WebGL指纹与显卡和驱动相关的3D渲染信息。字体列表你系统里安装的字体种类和顺序。屏幕分辨率与色彩深度。时区与语言。插件列表虽然现代浏览器已限制获取。HTTP协议特征如Accept-Encoding头部的顺序。如果你的爬虫脚本发出的请求其指纹特征与一个真实的Chrome浏览器不符或者成千上万个请求都来自同一个“指纹”那么无论你换多少IP都会被立刻识别并拦截。这就是为什么你会遇到那些看似莫名其妙的502错误或者404——你的请求在到达应用服务器之前可能就已经在网关层被风控系统基于指纹特征给干掉了。注意对抗的底线是法律与合规。本文讨论的技术仅用于学习、测试自家产品或在明确允许的范围内进行数据采集。切勿用于干扰目标网站正常运行、侵犯个人隐私或获取受法律保护的敏感数据。2.2 伪装体系的分层构建因此一个健壮的爬虫伪装体系应该像洋葱一样层层递进网络层伪装解决IP问题。使用高质量代理IP住宅代理、移动代理优于数据中心代理并合理设置切换策略。协议层伪装解决HTTP/S请求特征问题。完美模拟浏览器的请求头、TLS指纹JA3指纹、TCP连接行为等。浏览器环境伪装解决JavaScript执行与指纹问题。使用无头浏览器如Playwright、Selenium或携带完整浏览器环境的工具来生成真实的浏览器指纹。行为层伪装解决“像不像人”的问题。模拟人类的点击间隔、鼠标移动轨迹、滚动行为等。本指南将聚焦于第2层和第3层即HTTP请求伪装与浏览器指纹模拟的核心实战。3. 基础实战打造一个“以假乱真”的HTTP请求让我们从最基础的开始。一个真实的浏览器请求包含数十个头部字段而Python的requests库默认只携带极少数。第一步就是补全它们。3.1 请求头Headers的精细化伪造不要随便从网上复制一个User-Agent就了事。一个真实的请求头是自洽的。例如如果你的User-Agent声明是 Chrome 120 on Windows那么你的Accept-Language就应该是类似zh-CN,zh;q0.9,en;q0.8这样的值Sec-CH-UA用户代理客户端提示字段也需要对应更新。这里是一个模拟最新版Chrome浏览器的请求头字典示例它比常见的那些更“新鲜”也更不容易被标记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, # 客户端提示现代浏览器必带 Sec-CH-UA: Not_A Brand;v8, Chromium;v120, Google Chrome;v120, Sec-CH-UA-Mobile: ?0, Sec-CH-UA-Platform: Windows, # 接受的内容类型 Accept: text/html,application/xhtmlxml,application/xml;q0.9,image/avif,image/webp,image/apng,*/*;q0.8,application/signed-exchange;vb3;q0.7, Accept-Encoding: gzip, deflate, br, # 注意顺序gzip通常在前 Accept-Language: zh-CN,zh;q0.9,en-US;q0.8,en;q0.7, # 连接管理 Connection: keep-alive, # 来源页对于链式请求非常重要 Referer: https://www.google.com/, # 根据实际情况修改 # 缓存控制 Cache-Control: max-age0, # 升级不安全请求HTTPS站点 Upgrade-Insecure-Requests: 1, # 优先级提示 Sec-Fetch-Dest: document, Sec-Fetch-Mode: navigate, Sec-Fetch-Site: cross-site, Sec-Fetch-User: ?1, } session requests.Session() session.headers.update(headers) # 使用这个session发起请求 response session.get(https://www.xiaohongshu.com/explore)实操心得User-Agent需要定期更新。可以维护一个列表随机选取避免所有请求都用同一个。Referer字段非常关键。对于需要登录或具有严格来源检查的页面如小红书详情页必须正确设置上一个页面的URL。有时甚至需要模拟完整的浏览路径来设置一系列Referer。Accept-Encoding字段决定了服务器返回数据的压缩格式。requests库会自动处理gzip和deflate但如果服务器返回了br(Brotli) 压缩而你的请求头里没声明支持它可能就是一个异常点。不过requests默认不支持br这是一个小破绽在极高安全级别下需要考虑。3.2 会话Session管理与Cookie处理使用requests.Session()是必须的。它能自动处理Cookie保持连接池让你的多次请求看起来更像同一个浏览器会话内的连续操作。对于需要登录的网站先用Session对象模拟登录获取并保存Cookie后续的请求就会自动携带。# 模拟登录示例实际参数需分析目标网站 login_data { username: your_username, password: your_password, # 通常还会有csrf token等隐藏字段 } login_response session.post(https://www.xiaohongshu.com/api/sns/v1/user/login, datalogin_data) # 登录后session会自动管理cookies # 访问需要登录态的页面 profile_response session.get(https://www.xiaohongshu.com/user/profile)常见问题遇到登录失败除了检查账号密码更要检查登录请求是否包含了所有必要的隐藏字段如_csrf_token,captcha等这些字段往往需要先从登录页面解析出来。4. 进阶对抗使用Playwright应对动态渲染与基础指纹当目标网站大量使用JavaScript渲染内容或者简单的请求头伪装已经失效时我们就需要请出无头浏览器了。Playwright和Selenium是两大主流选择我个人更倾向于Playwright因为它由微软开发API更现代速度更快并且内置了对抗常见检测的机制。4.1 Playwright基础设置与隐身模式Playwright可以启动真实的Chromium、Firefox或WebKit浏览器内核。关键是要以“隐身”或“非自动化”模式启动以规避一些简单的navigator.webdriver检测。from playwright.sync_api import sync_playwright def crawl_with_playwright(url): with sync_playwright() as p: # 启动浏览器args参数可以传递各种启动选项来修改指纹 browser p.chromium.launch( headlessFalse, # 调试时可设为False看浏览器操作 args[ --disable-blink-featuresAutomationControlled, # 禁用自动化控制特征 --disable-dev-shm-usage, --no-sandbox, ] ) # 创建上下文类似一个独立的浏览器会话 context browser.new_context( viewport{width: 1920, height: 1080}, user_agentMozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36..., # 覆盖UA localezh-CN, timezone_idAsia/Shanghai, ) # 在上下文中创建页面 page context.new_page() # 注入JS进一步覆盖webdriver属性Playwright默认已做但双重保险 page.add_init_script( Object.defineProperty(navigator, webdriver, { get: () undefined }); window.chrome { runtime: {} }; // 模拟chrome对象 ) page.goto(url) # 等待页面加载或特定元素出现 page.wait_for_load_state(networkidle) # 获取页面内容 content page.content() # 或者执行JS获取数据 # data page.evaluate(window.__INITIAL_STATE__) browser.close() return content注意事项headless: True是无头模式节省资源但更容易被一些高级检测识别。对于强反爬网站可以考虑使用headless: False配合stealth模式需额外包或者直接使用playwright-stealth这样的插件。new_context非常重要。每个Context拥有独立的Cookie、缓存和指纹环境。通过创建多个Context来模拟多个不同的浏览器会话比创建多个浏览器实例更高效。4.2 绕过常见的自动化检测即使使用了无头浏览器你的脚本依然可能被检测到因为浏览器环境会暴露出一些自动化特征。除了上面代码中提到的--disable-blink-featuresAutomationControlled和覆盖navigator.webdriver还需要注意插件列表真实浏览器的navigator.plugins长度不为0而无头浏览器通常为0。可以通过注入JS来伪造。语言与语言偏好通过context设置locale和accept-language。屏幕分辨率通过viewport设置并确保与window.screen在JS中的值一致。时区通过timezone_id设置。一个更全面的环境设置示例context browser.new_context( viewport{width: 1366, height: 768}, user_agentrandom_user_agent, # 从列表随机选 localezh-CN, timezone_idAsia/Shanghai, permissions[geolocation], # 授予地理位置权限模拟 geolocation{latitude: 39.9042, longitude: 116.4074}, # 北京坐标 color_schemelight, reduced_motionreduce, # 偏好设置 # 覆盖权限模拟用户已授权通知等 extra_http_headers{ Accept-Language: zh-CN,zh;q0.9, } )5. 高阶指纹模拟与专用工具解析当面对小红书、TikTok、Facebook等顶级风控时上述手段可能依然不够。它们会检测更底层的指纹如Canvas、WebGL、AudioContext、字体哈希等。这时我们需要更专业的工具和策略。5.1 Canvas与WebGL指纹的原理与对抗Canvas指纹的原理是让浏览器用HTML5 Canvas API绘制同样的图形如一段文字、一个渐变。由于操作系统、图形硬件、显卡驱动、字体渲染引擎的细微差异最终生成的图像在像素级别会有极小的不同。将这个图像进行哈希运算就得到了一个唯一性很高的指纹。对抗方法不是去完全模拟某个特定值这几乎不可能而是“覆盖”或“稳定化”这个值使其在不同运行中保持一致避免被识别为不断变化的自动化脚本。使用playwright-stealth插件这个Python包封装了许多反检测技巧包括覆盖Canvas指纹。它会注入JS代码钩住hookCanvas的toDataURL和getImageData等方法返回一个确定性的、符合常见浏览器特征的值。pip install playwright-stealthfrom playwright.sync_api import sync_playwright from playwright_stealth import stealth_sync with sync_playwright() as p: browser p.chromium.launch(headlessTrue) context browser.new_context() page context.new_page() # 应用stealth模式 stealth_sync(page) page.goto(https://bot.sannysoft.com/) # 这是一个检测浏览器自动化特征的测试网站 # 截图或检查结果 page.screenshot(pathstealth_test.png) browser.close()手动注入指纹库有些开源项目如fingerprintjs提供了生成虚拟指纹的库。你可以预先生成一套完整的指纹数据Canvas哈希、WebGL渲染器、字体列表等然后通过page.add_init_script在页面加载前注入覆盖浏览器原生的API返回值。这种方法更灵活但实现复杂度高。5.2 字体指纹与媒体设备枚举浏览器能获取到系统安装的字体列表。这个列表很长且具有唯一性。对抗字体指纹同样需要覆盖navigator.fontsAPI。此外navigator.mediaDevices.enumerateDevices()可以枚举麦克风、摄像头等媒体设备。自动化环境通常返回空数组或固定设备。通过注入JS可以返回一个模拟的、合理的设备列表。实操心得字体和媒体设备指纹的覆盖通常也集成在playwright-stealth或类似的商业反检测浏览器方案中。对于绝大多数项目不建议从零开始自己实现成本太高且容易出错。5.3 专业指纹浏览器的选择与应用这就是热词中提到的“指纹浏览器”。它们不是普通的浏览器而是专门为多账号管理、爬虫、自动化测试设计的浏览器环境核心功能就是为每个浏览器配置文件提供独立、稳定、可定制的指纹。主流工具Multilogin、AdsPower、Dolphin Anty这些都是商业指纹浏览器。你可以创建无数个浏览器“配置文件”每个配置文件都有独立的Cookie、本地存储、指纹Canvas, WebGL, 字体 时区 语言 屏幕分辨率等。它们通常通过修改浏览器底层代码或驱动来实现完美的指纹隔离和模拟。浏览器指纹在线生成教程网上有很多教程教你如何用这些工具生成一个“完美”的指纹。核心步骤通常是创建配置文件 - 在指纹设置中选择“模拟真实浏览器”或手动设置各项参数建议选择“随机”或“跟随系统”- 启动浏览器环境 - 在这个环境中进行你的自动化操作可以通过Selenium或Playwright连接这些浏览器的调试端口进行控制。如何使用Playwright连接指纹浏览器 以AdsPower为例启动一个配置文件后它会开放一个本地调试端口如127.0.0.1:50325。你可以用Playwright连接到这个已经存在的浏览器实例而不是自己启动一个新的。from playwright.sync_api import sync_playwright def connect_to_fingerprint_browser(debug_port50325): with sync_playwright() as p: # 连接到已存在的浏览器实例 browser p.chromium.connect_over_cdp(fhttp://127.0.0.1:{debug_port}) # 获取第一个上下文通常指纹浏览器一个配置只有一个上下文 default_context browser.contexts[0] page default_context.pages[0] if default_context.pages else default_context.new_page() page.goto(https://www.xiaohongshu.com) # ... 你的操作 # 注意不要调用 browser.close()否则会关闭指纹浏览器窗口优势与代价优势指纹隔离彻底能有效对抗高级风控多账号管理方便通常集成代理IP设置。代价商业软件需要付费资源占用较高每个配置文件相当于一个独立的浏览器进程速度可能比纯代码方案慢。6. 实战案例构建一个抗封禁的小红书爬虫框架结合以上所有技术我们来设计一个针对小红书一个反爬非常严格的平台的爬虫框架思路。请注意这只是一个技术框架演示请严格遵守robots.txt和使用条款。6.1 架构设计我们的爬虫需要具备以下模块资源池管理模块管理代理IP、User-Agent列表、Cookie池如果需要多账号。请求引擎模块根据目标页面的反爬强度智能选择请求方式轻量级requests- 中级playwright- 高级指纹浏览器playwright。指纹管理模块如果使用指纹浏览器负责管理不同配置文件的启动、连接和轮换。行为模拟模块在页面内模拟人类浏览行为随机滚动、随机停留、随机点击非关键元素。异常处理与降级模块遇到429、502、验证码时自动重试、切换资源或触发更高级的伪装策略。6.2 核心代码逻辑示例import random import time from typing import Optional import requests from playwright.sync_api import BrowserContext, Page, sync_playwright class XHSAntiBlockSpider: def __init__(self, proxy_pool: list, user_agent_pool: list, use_fingerprint_browserFalse): self.proxy_pool proxy_pool self.user_agent_pool user_agent_pool self.use_fingerprint_browser use_fingerprint_browser self.playwright None self.browser None self.current_context: Optional[BrowserContext] None def __enter__(self): if self.use_fingerprint_browser: # 方案A连接指纹浏览器需提前手动或通过API启动一个配置文件 self.playwright sync_playwright().start() # 假设指纹浏览器调试端口在50325 self.browser self.playwright.chromium.connect_over_cdp(http://127.0.0.1:50325) self.current_context self.browser.contexts[0] else: # 方案B启动原生Playwright应用stealth插件 self.playwright sync_playwright().start() self.browser self.playwright.chromium.launch(headlessTrue, args[--disable-blink-featuresAutomationControlled]) self.current_context self.browser.new_context( viewport{width: 1366, height: 768}, user_agentrandom.choice(self.user_agent_pool), localezh-CN, # 可以设置代理 # proxy{server: random.choice(self.proxy_pool)} if self.proxy_pool else None ) from playwright_stealth import stealth_sync page self.current_context.new_page() stealth_sync(page) # 对第一个页面应用stealth其效果会延续到该context下的其他页面 page.close() # 关闭这个用于初始化的页面 return self def __exit__(self, exc_type, exc_val, exc_tb): if self.browser and not self.use_fingerprint_browser: self.browser.close() if self.playwright: self.playwright.stop() def fetch_with_retry(self, url, max_retries3): 智能获取页面优先尝试轻量级请求失败则升级策略 for retry in range(max_retries): try: if retry 0: # 第一层尝试轻量级requests 伪装头 return self._fetch_via_requests(url) elif retry 1: # 第二层尝试Playwright基础模式 print(f请求失败第{retry1}次重试使用Playwright) return self._fetch_via_playwright(url, use_stealthTrue) else: # 第三层尝试更复杂的行为模拟在当前context内 print(f请求失败第{retry1}次重试加强行为模拟) return self._fetch_via_playwright_with_behavior(url) except Exception as e: print(f第{retry1}次尝试失败: {e}) time.sleep(2 ** retry) # 指数退避 # 可以在这里切换代理IP或User-Agent raise Exception(f所有重试均失败URL: {url}) def _fetch_via_requests(self, url): 使用requests库获取适用于简单页面或API session requests.Session() headers { User-Agent: random.choice(self.user_agent_pool), Accept-Language: zh-CN,zh;q0.9, Referer: https://www.xiaohongshu.com/, } proxy random.choice(self.proxy_pool) if self.proxy_pool else None proxies {http: proxy, https: proxy} if proxy else None resp session.get(url, headersheaders, proxiesproxies, timeout10) resp.raise_for_status() # 检查返回内容是否包含反爬提示如跳转到验证页 if 验证 in resp.text or security in resp.url: raise Exception(触发验证需要升级策略) return resp.text def _fetch_via_playwright(self, url, use_stealthFalse): 使用Playwright获取页面 if not self.current_context: raise RuntimeError(Playwright上下文未初始化) page self.current_context.new_page() try: if use_stealth: from playwright_stealth import stealth_sync stealth_sync(page) # 模拟人类行为随机延迟后跳转 time.sleep(random.uniform(1, 3)) page.goto(url, wait_untilnetworkidle, timeout30000) # 再次随机滚动和停留 self._simulate_human_behavior(page) content page.content() # 检查页面是否正常加载而非验证码页 if page.title().lower().find(verify) ! -1: raise Exception(Playwright请求被重定向至验证页面) return content finally: page.close() def _fetch_via_playwright_with_behavior(self, url): 加强版Playwright增加更复杂的行为模拟 page self.current_context.new_page() try: from playwright_stealth import stealth_sync stealth_sync(page) # 更长的随机延迟 time.sleep(random.uniform(3, 7)) # 使用 goto 但监听请求可以随机取消一些非必要请求如图片来更像人类 page.goto(url, wait_untildomcontentloaded, timeout40000) # 复杂行为模拟 self._simulate_human_behavior(page, intensiveTrue) # 等待可能由JS触发的内容加载 page.wait_for_timeout(random.uniform(2000, 5000)) content page.content() return content finally: page.close() def _simulate_human_behavior(self, page: Page, intensiveFalse): 在页面上模拟人类浏览行为 # 随机滚动 scroll_times random.randint(3, 7) if intensive else random.randint(1, 3) for _ in range(scroll_times): # 随机滚动距离 scroll_height random.randint(200, 800) page.evaluate(fwindow.scrollBy(0, {scroll_height})) time.sleep(random.uniform(0.5, 2.0)) # 随机停留 # 偶尔随机移动鼠标到某个元素上但不点击 if intensive and random.random() 0.5: all_links page.locator(a).all() if all_links: random_link random.choice(all_links) random_link.hover() time.sleep(random.uniform(0.3, 1.2)) # 使用示例 if __name__ __main__: proxy_list [http://user:passip:port, ...] # 你的代理列表 ua_list [Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36..., ...] # 你的UA列表 # 方案1使用原生Playwright stealth (应对中等反爬) with XHSAntiBlockSpider(proxy_list, ua_list, use_fingerprint_browserFalse) as spider: html spider.fetch_with_retry(https://www.xiaohongshu.com/explore) print(len(html)) # 解析html... # 方案2使用指纹浏览器 (应对高级反爬需额外配置) # with XHSAntiBlockSpider([], ua_list, use_fingerprint_browserTrue) as spider: # html spider.fetch_with_retry(https://www.xiaohongshu.com/user/profile/xxx) # print(len(html))这个框架提供了一个弹性策略。对于小红书首页探索页这类反爬相对宽松的页面可能第一层requests就能成功。对于用户详情页、搜索列表页这些重灾区则会自动降级到使用Playwright甚至更复杂的行为模拟。7. 常见问题排查与调试技巧在实际操作中你会遇到各种各样的问题。下面是一些常见错误和排查思路。7.1 高频错误码解析与应对状态码/错误信息可能原因排查与解决思路403 ForbiddenIP被封、请求头不完整或被识别、Cookie失效、签名验证失败。1. 更换代理IP。2. 检查并补全所有关键请求头特别是Referer,User-Agent,Cookie。3. 对于有签名算法的API需要逆向JS计算x-sign,x-t等参数。429 Too Many Requests请求频率过高。1. 立即大幅降低请求频率加入随机延迟time.sleep(random.uniform(1, 5))。2. 检查是否并发过高减少并发数。3. 使用更优质的代理IP池住宅IP。502 Bad Gateway你的请求被前置的风控网关如WAF、防爬虫服务拦截未到达应用服务器。这是指纹或协议特征被识别的典型标志。1. 检查TLS指纹JA3考虑使用curl_cffi等库模拟真实浏览器TLS。2. 加强浏览器指纹模拟使用Playwright stealth或指纹浏览器。3. 尝试使用移动端User-Agent和头部。404 Not Found页面不存在或URL带有动态令牌且已过期或请求被重定向到404页。1. 确认URL是否正确。2. 对于需要动态令牌的URL检查令牌生成逻辑和有效期。3. 可能是风控策略返回假404。尝试用浏览器手动访问同一URL验证。无限重定向或跳转到验证码会话无效或指纹被识别触发验证流程。1. 检查Cookie是否有效且新鲜。2. 检查浏览器指纹特别是Canvas/WebGL是否暴露。使用测试网站如bot.sannysoft.com检测。3. 考虑引入验证码识别服务如打码平台进行交互。7.2 调试与检测工具推荐浏览器开发者工具 (F12)最基础也是最重要的工具。查看Network面板中每个请求的Headers特别是Request Headers、Cookies、Preview/Response。使用Copy as cURL功能可以快速复现浏览器发出的原始请求。指纹检测网站https://bot.sannysoft.com/检测无头浏览器和自动化特征。https://antoinevastel.com/bots/检测更高级的浏览器指纹和自动化工具。https://pixelscan.net/专注于Canvas和WebGL指纹检测。在你自己编写的爬虫中访问这些网站查看检测结果针对性改进。Playwright/Chromium 开发者工具在启动Playwright时设置devtoolsTrue可以打开浏览器开发者工具实时查看Console日志和Network请求对于调试页面内的JS错误和请求拦截非常有用。Wireshark / Fiddler网络抓包工具可以分析最底层的TCP/TLS握手信息对于调试罕见的网络层问题有帮助。7.3 关于“unexpected status 502 bad gateway”的深度排查这个错误在爬虫中极其常见尤其是在使用云服务器或代理时。除了上述指纹问题还需排查代理IP质量你使用的代理IP可能已被目标网站拉黑或者本身就不稳定。尝试更换为住宅ISP代理或4G/5G移动代理它们的IP段更接近真实用户。TLS指纹JA3你的爬虫程序如Python的requests、aiohttp在建立TLS连接时其加密套件、扩展列表的顺序与真实浏览器不同会生成独特的JA3指纹。风控系统可以据此识别。解决方案是使用能修改TLS指纹的库如curl_cffi模拟真实浏览器TLS指纹的Python库或直接使用无头浏览器其TLS指纹与真实浏览器一致。TCP连接特征如TCP窗口大小、TTL等。这部分较难修改但使用真实浏览器内核Playwright通常能解决。一个简单的JA3指纹测试你可以用curl命令和curl_cffi分别请求https://tls.browserleaks.com/json对比返回的ja3_hash字段。如果不同说明你的Python默认HTTP库指纹暴露了。踩坑这么多年我的体会是爬虫与反爬的对抗没有一劳永逸的银弹。它是一个持续迭代的过程。今天有效的指纹明天可能就被加入特征库。最稳妥的策略是“模拟真实用户”和“分散风险”。用真实浏览器环境、注入人类行为、使用高质量且分散的代理IP、严格控制访问频率并将这些策略组合成一个有弹性的系统才能在数据采集的路上走得更远。最后再分享一个小技巧对于非常重要的目标不妨准备几套完全不同的技术方案如纯请求、Playwright、指纹浏览器并设置一个熔断机制当一种方案失败率过高时自动切换这能极大提高系统的鲁棒性。