资讯动态

Selenium爬虫反检测:6个动作伪装成真人,绕过验证码与IP封锁

发布时间:2026/10/9 23:12:39 来源:尧图企业网站定制
做Selenium爬虫的人基本都遇到过这类场景脚本刚跑起来页面正常打开数据也加载了一部分然后突然弹出一个验证框或者网页直接返回一片空白再看控制台一行“拒绝访问”的报错躺在那里。我刚开始接触爬虫那几年总觉得是代码哪里写错了后来才发现根本不是代码的问题——是网站的反爬系统已经认出你是一个浏览器自动化程序而不是一个真人用户。这个识别过程其实没有你想的那么玄乎。反爬系统会从浏览器特征、运行指纹、操作行为等多个维度同时打分一旦“机器人痕迹”太多就把你标记出来轻则弹验证码重则直接拉黑IP。Selenium虽然是目前最主流的浏览器自动化工具可它天生带着不少能被识别的“出厂设置”所以才需要后天的伪装和调整。这篇文章我会用一套组合拳把我在真实项目中验证过的6个关键动作完整拆解出来。每一个动作都会讲清楚“为什么有效”给出可以直接复制的Python代码也会把我踩过的坑一起说出来。内容适合两类人看一类是刚开始写爬虫、经常被验证码拦下来的新手另一类是已经在用Selenium做数据采集想提升稳定性和采集效率的老手。这套方案不能保证100%绕过所有检测但至少可以让你从“每次都被识别”进阶到“大多数时候看起来都像个正常人”。1. 反爬系统到底是怎么认出Selenium的想做好规避先得搞清楚对面的“侦查武器”是什么。反爬系统识别Selenium并不是靠某一个单独的特征而是综合多项线索来下定论。我把它们归纳成三个层面。1.1 navigator.webdriver最扎眼的“真身标志”浏览器本身有几个JavaScript属性是专门给自动化测试工具用的其中最关键的就是navigator.webdriver。普通的Chrome浏览器这个值是undefined而Selenium驱动的Chrome这个值往往是true。反爬系统只要跑一行JS代码就能立刻判断出你是不是自动化程序。这个字段是Selenium被识别的头号原因。它之所以存在是因为WebDriver规范要求自动化会话对页面公开自己的身份方便开发者调试。但站在爬虫的角度来说这个“身份信息”就是我们必须清除的破绽。除了navigator.webdriver之外还有一些衍生痕迹比如window.cdc_开头的变量名Chromium Driver相关的内部标识、Chrome插件列表里多出来的扩展项。这些都是早期Selenium版本留下的“指纹”虽然现在的反爬系统不一定每个都查但能隐藏就隐藏尽量把暴露面降到最低。1.2 浏览器指纹多维度交叉验证就算你清掉了navigator.webdriver反爬系统还会通过浏览器指纹来继续判断。指纹的意思就是浏览器在很多细节上的参数组合比如屏幕分辨率和可视区域大小screen.width、window.innerWidth操作系统标识navigator.platform、navigator.userAgent语言和时区navigator.language、Intl.DateTimeFormat().resolvedOptions().timeZoneCanvas绘图指纹通过绘制特定图形后提取像素数据WebGL渲染信息显卡型号、渲染参数字体列表、音频处理参数等等真实用户打开Chrome这些参数之间是高度自洽的。比如一个Windows系统用户通常屏幕分辨率会是1920x1080或2560x1440UA里会带Windows NT 10.0但如果我们让Selenium在Linux服务器上跑又不改UA就会出现“操作系统是Linux屏幕尺寸却和手机一样”这种明显矛盾反爬系统一查就露馅。1.3 行为节奏机器人还是真人浏览器特征之外反爬系统还会观察你的操作行为。真人浏览网页的时候鼠标会有加速度、会有小范围抖动滚动页面是一段一段的点击按钮之前会停顿一两秒来“思考”。但Selenium默认的click()方法鼠标是瞬间跳跃到目标位置点击间隔异常规律滚动条直接跳到指定位置。一套成熟的反爬系统会把行为数据采集下来用机器学习模型做分类判断。当出现“鼠标移动速度极快、点击前无停留、页面滚动由脚本控制”这些特征时即便浏览器指纹伪装得再像行为模型也会给你打一个较低的“人类分数”。所以后面我要讲的6个动作里行为模拟和指纹伪装是密不可分的两半。2. 动作一用CDP启动注入先干掉navigator.webdriver这个“卧底标志”这是基础中的基础。如果navigator.webdriver还是true后面再怎么做指纹伪装都是白搭。我第一次做规避处理时就是先从这里下手的。2.1 理解CDP浏览器的“远程控制协议”CDP的全称是Chrome DevTools Protocol是Chrome提供给开发者工具的调试协议。Selenium的execute_cdp_cmd方法可以让我们在浏览器启动之后直接向浏览器底层发送命令其中有一个命令叫Page.addScriptToEvaluateOnNewDocument。这个命令的作用是在浏览器加载任何一个新页面之前先执行一段你指定好的JavaScript。你可以理解为“页面刚开始加载时先往里面打一针预防针”让页面在执行自身脚本之前就认为navigator.webdriver根本不存在。2.2 动手实践三行代码清除webdriver标志下面这段代码是我在项目里一直沿用的最小清除方案from selenium import webdriver from selenium.webdriver.chrome.options import Options options Options() # 去掉“Chrome正在被自动化软件控制”的提示条 options.add_experimental_option(excludeSwitches, [enable-automation]) # 不加载自动化扩展 options.add_experimental_option(useAutomationExtension, False) # 禁用Blink引擎的自动化控制特征 options.add_argument(--disable-blink-featuresAutomationControlled) driver webdriver.Chrome(optionsoptions) # 核心动作在每一个新文档加载之前重写navigator.webdriver属性 driver.execute_cdp_cmd(Page.addScriptToEvaluateOnNewDocument, { source: Object.defineProperty(navigator, webdriver, { get: () undefined }); }) # 跳转到目标页面 driver.get(https://example.com) # 验证一下输出应该是 undefined print(driver.execute_script(return typeof navigator.webdriver))这段脚本里最关键的是Object.defineProperty这行代码。它重新定义了navigator.webdriver这个属性的getter方法让页面在读取时永远得到undefined。注意这里我用了get: () undefined而不是get: () false因为有些网站会判断值是否存在undefined更贴近正常浏览器的表现。2.3 常见误区执行时机比代码本身更重要有一个坑我必须要提醒driver.execute_cdp_cmd必须在driver.get()跳转页面之前执行。因为Page.addScriptToEvaluateOnNewDocument只对“之后加载的文档”生效如果先进入了目标页面再执行这段命令当前页面已经加载完了里面的检测脚本早就跑完了你之后再注入就来不及了。另外要注意的是excludeSwitches里的enable-automation选项在部分Chrome版本上已经不再生效了。别管网上那些老教程怎么说的实际测试发现--disable-blink-featuresAutomationControlled这个参数在很多新版本Chrome上直接写进options里的效果更稳定。我的建议是两者都写上多一层保险总归没坏处。3. 动作二把浏览器指纹伪装得“严丝合缝”清除navigator.webdriver只是第一步接下来要做的是把浏览器的指纹整体调整到和真人一致。这里说的“一致”不只是某个参数改对了而是所有参数组合起来要自洽不能互相矛盾。3.1 一份必须自洽的指纹清单我给你整理了一份我在实战中必查的指纹清单。每次启动浏览器之前我都会把这些参数过一遍确保它们之间没有逻辑冲突指纹项取值示例自洽性要求操作系统Windows 10与UA里的Windows NT 10.0对应User-AgentChrome 120.0 Windows版本不能出现“Mac UA Windows平台”的组合屏幕分辨率1920x1080注意--window-size设置的是可视区域不等于完整屏幕分辨率有时候需要额外设置设备缩放比1高清屏可能出现1.25或1.5要和分辨率匹配语言zh-CN, zh;q0.9与浏览器界面语言、页面Content-Language一致时区Asia/Shanghai与操作系统的时区设置一致频繁切换目标站点地区时要小心Canvas指纹默认不篡改不建议手动改动容易弄巧成拙WebGL渲染器真实显卡或常见软件渲染如果禁用WebGL反爬系统反而会怀疑你可能会问为什么时区也这么重要因为浏览器时区信息是从操作系统读取的。如果服务器部署在美国目标网站是国内站反爬系统发现你的浏览器时区是America/New_York但页面语言和UA都是中文这个组合在正常用户里很少见就会提高你的异常分。3.2 用Options参数给浏览器重新“塑身”在Selenium里调整指纹主要靠Options参数。下面是我常用的一个“塑身”配置from selenium import webdriver from selenium.webdriver.chrome.options import Options options Options() # 隐藏自动化痕迹动作一的加强版 options.add_argument(--disable-blink-featuresAutomationControlled) options.add_experimental_option(excludeSwitches, [enable-automation]) options.add_experimental_option(useAutomationExtension, False) # 指纹塑造 options.add_argument(--user-agentMozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36) options.add_argument(--window-size1920,1080) options.add_argument(--langzh-CN) options.add_argument(--force-device-scale-factor1) options.add_argument(--timezoneAsia/Shanghai) # 这里需要把操作系统的时区也尽量保持一致 # 在Linux服务器上可以通过环境变量 TZAsia/Shanghai 来设置 driver webdriver.Chrome(optionsoptions) # 验证关键指纹 print(driver.execute_script(return navigator.userAgent)) print(driver.execute_script(return screen.width x screen.height)) print(driver.execute_script(return new Date().toString().match(/\\(([^)])\\)/)[1]))这里有一个细节--user-agent虽然改了UA但navigator.platform这个属性不会跟着变。在Windows上它通常是Win32在Linux上是Linux x86_64。如果UA显示Windows但navigator.platform是Linux那就是一个互相矛盾的破绽。所以对于Linux服务器跑Selenium的情况我会考虑用--user-agent的同时再用CDP注入修改navigator.platformdriver.execute_cdp_cmd(Page.addScriptToEvaluateOnNewDocument, { source: Object.defineProperty(navigator, platform, { get: () Win32 }); })这个方法可以顺便把navigator.language这类属性一起统一改掉比依赖浏览器启动参数更灵活。3.3 如何验证指纹是否有效很多人改完参数就直接开跑结果被拦截了还不知道为什么。我建议在正式采集之前先打开目标网站手动执行一段JS脚本把关键指纹全部打印出来看一遍console.log({ userAgent: navigator.userAgent, platform: navigator.platform, language: navigator.language, webdriver: navigator.webdriver, timezone: Intl.DateTimeFormat().resolvedOptions().timeZone, screen: screen.width x screen.height, outer: window.outerWidth x window.outerHeight, inner: window.innerWidth x window.innerHeight });执行之后逐项检查尤其是webdriver必须是undefinedtimezone必须正确。我遇到过很多次改了一大堆参数结果一查发现outerWidth比innerWidth只差十几像素说明浏览器带滚动条和窗口尺寸参数不匹配反爬系统靠这个也能判断出异常。4. 动作三隐藏Chrome的自动化痕迹别让控制台属性出卖你除了navigator.webdriverChrome浏览器在自动化模式下还有一些“身份标记”藏在浏览器内部。这些标记普通人看不到但反爬系统的检测脚本一跑就能发现。4.1 关闭“正在受自动化软件控制”提示条当你用Selenium启动Chrome的时候浏览器顶部会显示一条黄色的提示条“Chrome正在受到自动测试软件的控制。”这是默认开启的自动化提示也是直觉上最容易被发现的破绽。对应的处理方式是options.add_experimental_option(excludeSwitches, [enable-automation])这个选项会把Chrome的自动化控制开关从启动参数里排除掉。加上这行之后那个黄色提示条就不会出现了。注意这里说的是“排除自动化开关”和后面要讲的--disable-blink-features是两个不同层面的操作但两者往往一起用。4.2 禁用Blink引擎上的AutomationControlled特性Chrome的内核叫做Blink它会根据是否处于自动化控制状态暴露一些接口或者改变一些行为。AutomationControlled就是由Blink层暴露出来的一个特征。禁用它的写法很简单options.add_argument(--disable-blink-featuresAutomationControlled)这个参数的作用是关闭Blink引擎上的自动化控制标记让页面脚本在遍历浏览器特性时看不到和自动化有关的痕迹。实测下来这个参数对于部分检测能力较强的网站依然有效是清单里的常青树。4.3 处理残留的CDP注入变量有些是在浏览器已经启动之后页面能够检测出来的内部变量。比如说部分旧版本的Selenium/ChromeDriver会在window上挂一个cdc_开头的属性。这个属性是ChromiumDriver的缩写但正常浏览器里根本没有这个名字的变量。这个残留变量在较新的ChromeDriver版本中已经越来越罕见了但如果你还在用老版本我建议升级一下驱动版本。有一个简单的排查方法在目标页面里执行Object.keys(window).filter(k k.startsWith(cdc_))如果返回了结果说明你的浏览器环境里还有这种特征需要考虑切换驱动版本或做进一步注入清理。这里我要特别说一句网上有很多教程会教你用正则替换Chromedriver里的cdc_关键字以此来欺骗检测。这种方式在原理上是可行的但会破坏Chromedriver的签名和完整性一旦网站升级检测策略可能适得其反。我的建议是优先用组件升级和配置调整来解决不要一上来就动二进制文件。5. 动作四像人一样移动鼠标、滚动页面告别“机械式操作”指纹和特征都伪装完之后还有一个环节很多人会忽略操作行为。Selenium默认的click()和send_keys()太“直来直去”了反爬系统看你的行为轨迹一眼就能识别出机器人。5.1 Selenium原生操作为什么会被行为识别真人点击一个按钮鼠标不会凭空瞬移到按钮中心。你的手部会带动鼠标先快速移动到按钮附近然后慢速微调最后落点可能在按钮中心也可能偏左几个像素。整个移动过程是有加速、减速、甚至小幅过冲的曲线。而Selenium默认的click()本质上是给浏览器发一个指令把鼠标指针放到元素中心然后按下。页面里记录的鼠标事件是一个从某个位置瞬间跳到目标位置、立即点击的过程。检测系统只要计算一下鼠标移动速度就会发现这个速度远远超过人类极限于是直接标记为自动化操作。5.2 用ActionChains模拟鼠标轨迹我之前在采集过程中写了一个模拟鼠标移动的辅助函数核心思路是把一次鼠标移动拆成多个小段每段带随机偏移和随机间隔import random import time from selenium.webdriver.common.action_chains import ActionChains def human_mouse_move(driver, target_element): 把鼠标从当前位置移动到目标元素上模拟人类轨迹 action ActionChains(driver) # 先获取目标元素的位置和尺寸 target_x target_element.location[x] target_element.size[width] / 2 target_y target_element.location[y] target_element.size[height] / 2 # 获取当前鼠标位置 current_x, current_y 0, 0 # 这里需要根据场景实际初始化 # 计算移动总距离 distance_x target_x - current_x distance_y target_y - current_y # 将移动拆成随机数量的步骤模拟加速和减速 steps random.randint(10, 20) for i in range(steps): progress (i 1) / steps # 先快后慢模拟人的移动特性 eased_progress progress ** 1.5 move_x int(current_x distance_x * eased_progress) move_y int(current_y distance_y * eased_progress) action.move_by_offset(move_x - current_x, move_y - current_y) action.perform() time.sleep(random.uniform(0.01, 0.05)) current_x, current_y move_x, move_y # 最后移动到目标中心再额外加一点随机偏移 jitter_x random.randint(-3, 3) jitter_y random.randint(-3, 3) action.move_by_offset(jitter_x, jitter_y).perform() time.sleep(random.uniform(0.1, 0.3)) target_element.click()这段代码里面progress ** 1.5是用幂函数做的缓动效果让鼠标在开始阶段移动快、接近目标时移动慢符合人手运动的基本规律。当然这个函数只是提供了一个基础框架不同网站的检测维度不一样你可能还需要根据实际情况调节步长和间隔。5.3 滚动和输入的节奏也要“人化”除了鼠标移动滚动也是行为检测的高频观察点。真人看网页是看一段滚一段中间会有停顿有时候还会往回调一点。而Selenium脚本如果用driver.execute_script(window.scrollTo(0, document.body.scrollHeight))就是一秒不到直接拉到底毫无悬念。我习惯把滚动拆成多次每次滚动距离随机之间的间隔也随机def human_scroll(driver, max_scroll): current_position 0 while current_position max_scroll: # 每次滚动随机一段距离 scroll_step random.randint(200, 600) current_position scroll_step current_position min(current_position, max_scroll) driver.execute_script(fwindow.scrollTo(0, {current_position});) # 随机停一下有时候往回滚一点 time.sleep(random.uniform(0.3, 1.0)) if random.random() 0.2: back_step random.randint(50, 150) current_position max(0, current_position - back_step) driver.execute_script(fwindow.scrollTo(0, {current_position});) time.sleep(random.uniform(0.2, 0.5))输入文字也一样。真人在表单里填内容是一个字一个字敲出来的速度和按键间隔有波动。而send_keys()一次性把所有文本灌进去速度极快。对于比较严格的站点我建议用逐字输入再配合随机延迟的方式def human_input(element, text): for char in text: element.send_keys(char) time.sleep(random.uniform(0.05, 0.2))这三个函数组合起来你的Selenium才能从“机器人行为模式”切换成“真人行为模式”。6. 动作五启动参数和服务选项的工程化配置前面几个动作侧重于“伪装”动作五则更偏向工程部署层面的稳定性。指纹、行为都优化了但如果浏览器本身运行在一个被反爬系统认为“不常规”的环境里一样会露馅。6.1 常用启动参数对照表我把Selenium启动Chrome时常用的参数整理了一份对照表你可以直接拿来参考参数作用备注--disable-blink-featuresAutomationControlled关闭自动化控制特征动作三已经讲过必加--disable-gpu禁用GPU加速服务器环境没有GPU时建议启用避免渲染异常--no-sandbox关闭沙盒模式在Docker或容器环境中必须加--disable-dev-shm-usage禁用/dev/shm共享内存容器环境内存受限时建议加--window-size1920,1080设置浏览器窗口大小直接影响window.outerWidth等参数--langzh-CN设置浏览器界面语言指纹自洽需要--disable-extensions禁用浏览器扩展减少指纹特征点--disable-notifications禁用通知弹窗避免网站活动弹窗干扰脚本--incognito隐身模式部分网站对隐身模式有策略谨慎使用--user-data-dir路径指定用户数据目录多实例隔离、提升稳定性常用6.2 无头模式的取舍与优化无头模式headless是爬虫场景里的重灾区。options.add_argument(--headless)虽然能让浏览器在后台运行不弹出窗口更省资源但无头模式下的Chrome很多特征和正常模式差别很大比如UA字符串里默认带HeadlessChrome字样这就是一个明晃晃的标志WebGL、Canvas的渲染结果可能和正常模式不一致字体列表、系统API的暴露程度都不同所以我的建议是优先尝试有头模式。如果你的服务器有图形环境或者你只是在个人电脑上跑程序直接去掉--headless参数就好。如果确实因为服务器环境必须用无头模式那你至少要做两件事第一件事把UA改成正常Chrome的UA去掉HeadlessChrome字样第二件事加上--window-size设置一个常见的屏幕分辨率减少无头模式默认尺寸带来的暴露风险。# 一个相对稳妥的有头模式配置模板 options Options() options.add_argument(--disable-blink-featuresAutomationControlled) options.add_experimental_option(excludeSwitches, [enable-automation]) options.add_experimental_option(useAutomationExtension, False) options.add_argument(--user-agentMozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36) options.add_argument(--window-size1920,1080) options.add_argument(--langzh-CN) options.add_argument(--disable-gpu) options.add_argument(--no-sandbox) options.add_argument(--disable-dev-shm-usage)6.3 注意浏览器版本和Driver版本的匹配这个属于工程层面最容易被忽略的细节但雷区极大。Chrome升级是很频繁的ChromeDriver如果跟不上Chrome的版本启动时会直接报错“session not created: This version of ChromeDriver only supports Chrome version xxx”。遇到这种问题别慌去ChromeDriver的官方下载页找到和当前Chrome版本完全一致的驱动替换掉即可。版本匹配这件事没有捷径你只能老老实实看两个版本号保持一致。我在采集环境里都会用一个自动化小脚本来定期检查Chrome版本和本地Driver版本做对比一旦出现大版本差异就自动提示我更新。7. 动作六频率控制、调度策略和验证码的实战应对前面的动作都是“单次访问时不让网站认出你”但数据采集是一个长期过程。就算你伪装得再好如果请求频率太高行为节奏再像人也白搭。频率策略和调度能力决定了整个采集任务能持续多久。7.1 请求频率宁可慢不可死我发现很多爬虫新手容易掉进一个陷阱以为爬得快等于效率高。实际上对大部分中等体量的站点来说控制频率才是效率的根本保障。一次采集任务哪怕要跑10个小时只要你没被封就是一次成功但如果跑半小时就被封IP之前的所有投入都清零了。频率控制的做法很简单在每次请求之间加一个随机延时import random import time def random_sleep(base3, variance2): 随机延迟让请求间隔更像真人操作 time.sleep(max(0.1, base random.uniform(0, variance)))这个函数里base和variance的值要根据目标站点的访问压力来调整。对于比较敏感的站点我通常会把间隔放到5到10秒对于自身流量很大的平台可以适当缩小到1到3秒。原则就是你不确定的时候先慢后快逐步试探。7.2 封IP后的延迟退避策略即便你频率控制得再好也有被反爬策略盯上的可能。一旦发现请求开始出现异常比如频繁出现验证码、页面返回特定错误码最忌讳的做法是继续用同一个IP硬冲。这时候应该启动延迟退避策略第1次被封暂停5分钟 第2次被封暂停30分钟 第3次被封暂停2小时等于是给网站一个“冷却期”等风控阈值降下来再恢复采集。这个策略我实测下来非常有效能极大减少因为连续点击被拉黑的情况。7.3 面对验证码优先用行为引导而不是硬破解验证码是规避检测绕不过去的一环。滑块验证码、点选验证码、数字验证码都已经成为主流网站的标配。我的观点是遇到验证码第一步想的不应该是“用什么平台去打码”而是“为什么我触发了验证码”。如果前面几个动作都做到位了大部分场景你根本碰不到验证码。如果你确实需要处理滑块验证码那么在写代码时要注意模拟“拖拽轨迹”的连贯性而不是简单地从A点拖到B点。很多失败的案例都是因为拖动速度过于均匀真实用户的拖动应该是一段慢、中间快、最后再慢下来的过程。如果你要用第三方打码服务也尽量选带轨迹模拟能力的这样可以提高通过率。8. 常见问题与排查技巧实录最后这部分我把这些年做Selenium采集时遇到的典型问题整理成一个排查手册。很多问题看着复杂实际上都有固定的处理套路。8.1 改了navigator.webdriver还是被检测这种情况我遇到过很多次。排查思路是这样的先检查是不是JS注入顺序错了确认execute_cdp_cmd确实在driver.get()之前执行然后手动打印navigator.webdriver的值如果显示undefined说明第一层没问题问题大概率出在别的指纹上。常见的“别的指纹”包括Canvas指纹异常页面脚本能画出和正常浏览器不一样的像素、WebGL渲染器信息暴露服务器没有GPU会导致渲染器名称是SwiftShader、以及浏览器插件列表为空正常用户多少会装几个插件空列表反而不正常。针对这些我的建议是不要一次性追求所有指纹都像真人先把最容易被发现的三个搞定UA、屏幕尺寸、时区稳扎稳打。8.2 无头模式一开就被识别如果你设置--headless之后发现目标网站立刻返回异常我基本可以断定是UA里带了HeadlessChrome。排查方法是// 在页面中执行查看UA是否包含Headless navigator.userAgent.includes(Headless)如果是这个原因手动指定一个不带Headless标识的UA即可。如果UA没问题再查WebGL的渲染器名称无头模式下通常是SwiftShader这也是一个强力识别点。为了绕开这个坑我一般会在无头模式下启动之前查一下目标网站用到的JS库比如是不是用了fingerprintjs然后针对性调整相关指纹。8.3 IP被封怎么判断该等还是该换封IP之后很多人第一反应是换代理继续跑。但如果是同一台机器、同一个浏览器指纹只是换了一个IP反爬系统照样能通过指纹把你关联起来。所以我的建议是先确认封禁范围。如果你换一个普通浏览器访问同一个目标网站发现完全正常说明IP级别的封禁居多这时可以等待冷却或更换IP如果换浏览器后也异常那就要回头检查指纹和代码逻辑了。另外不管用什么通道换IP都要确保新IP的归属地和你的指纹参数一致。比如你的浏览器时区设置为Asia/Shanghai但新IP的归属地显示在欧洲这几个信息组合起来就会非常可疑。所以每次更换IP之后我都会重新跑一遍上面提到过的指纹验证脚本确保整体参数依然自洽。8.4 一个简单的自检清单开跑前过一遍我每次上线新的采集脚本都会过一遍下面这份自检清单全部通过才放行检查项方法预期结果webdriver属性页面执行JSundefinedUA页面执行navigator.userAgent正常Chrome UA无Headless字样屏幕尺寸screen.width/height和你设置的窗口尺寸一致时区Intl.DateTimeFormat().resolvedOptions().timeZone和目标地区一致平台navigator.platform和UA里的系统一致行为速度观察鼠标轨迹间隔有加速减速非匀速瞬移请求间隔日志记录每次间隔随机非固定值这份清单的检查过程本身很花时间但带来的收益是实实在在的稳定。我宁可多花10分钟做自检也不愿意跑了一下午才发现从头到尾都在被反爬系统“看戏”。讲到这里6个动作就全部拆完了。我在实际项目中最大的体会是规避检测不是某一个技巧的比拼而是一个系统工程。从浏览器启动参数、指纹伪装、CDP注入到操作行为、频率控制每一个环节都必须做到位单点突破的意义不大。另外也想提醒一句这套方法和代码请只在你有合法数据使用权的站点上使用尊重目标网站的robots协议和服务条款。反爬与爬虫的博弈永远在动态变化今天有效的参数明天可能就会被新的检测策略覆盖保持学习和迭代的心态比记住任何一个固定配置都更重要。最后送你一个小技巧把指纹验证脚本保存成一个单独的JS文件每次换配置后先跑一遍再开始采集你会少踩很多无意义的坑。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑