爬虫伪装得再好,为什么还是被网站识破?

你写的爬虫刚跑起来,IP就被封了。不是代理不行,也不是User-Agent没换,而是网站压根没信你是人——它早把你的“行为痕迹”当成了异常信号。

别急着改代码。先想想:你上次手动逛这个网站时,是不是也点了首页、停了几秒、又点进某篇文章?是不是中途还切出去回了条消息?爬虫要学的,从来不是“怎么发请求”,而是“怎么像个人一样,在网站上待着”。

为什么加随机延时还是被抓?你漏了“行为密度”

延时不是加了就行,关键得像真人那样“有节奏”。

真人不会每点一下就掐表等3秒。他可能在首页晃12秒,点开文章后读到一半去倒水,回来再往下拉;也可能连刷三篇,中间只隔两秒——这些都不是均匀分布,而是有起有伏、有停有走。

我的教训:
爬一个技术论坛时,我用了random.uniform(2,5)设延时,结果第30次请求就被拦截。后来我录了10个真实用户操作,发现他们平均一分钟只发起4次请求,而且80%的操作集中在晚上8–10点。我把爬虫调成按这个节奏跑,同一个IP撑了2小时没触发风控。

具体做法:
打开目标网站,自己手动操作一遍,用手机秒表记下每一步的时间戳(比如:打开首页→停3.2秒→点进帖子→停8.7秒→返回列表→停1.5秒)。把这些数字导进Excel,算出间隔分布,再让爬虫照着这个分布调度请求——别再用time.sleep()硬凑数字了。

你的请求头里藏着哪些“人味”不足的破绽?

User-Agent只是入门级伪装。现在网站看的是你“像不像一个正在用浏览器的人”,而不是“像不像某个浏览器”。

它们会查你TLS握手时的细节、HTTP/2帧的发送顺序、甚至页面渲染过程中Canvas画布的像素抖动。这些你没法手写模拟,除非直接用真浏览器。

一个真实案例:
朋友公司做电商比价,用Selenium启动Chrome,理论上和真人一模一样。结果5分钟内就被弹验证码。排查三天才发现:Selenium默认窗口是800×600,而真实用户几乎没人用这个尺寸;更致命的是,navigator.webdriver这个属性明晃晃写着true——等于在额头贴字:“我是脚本”。

你该检查的破绽:

  • 浏览器窗口尺寸别写死,从1280x7201366x7681920x1080里随机选
  • 用Chrome DevTools协议关掉navigator.webdriver,或者加启动参数--disable-blink-features=AutomationControlled
  • 字体列表、显卡信息、系统时区——这些都会在Canvas指纹里暴露出来,别留默认值

网站如何用“鼠标轨迹”和“滚动模式”分辨你和真人?

鼠标不动、滚动条直跳到底?系统一眼看出你在“赶任务”,不是在“找内容”。

很多反爬系统会监听mousemovewheeltouchstart这些事件。如果页面加载完3秒内,鼠标坐标没变过,或者滚动高度瞬间从0跳到5000px,它立刻判定:“这不是人。”

我踩过的坑:
爬一个图片素材站,用Puppeteer加载页面后直接取数据,结果一直卡在Cloudflare的JS挑战页。后来发现:页面加载完后我没模拟任何滚动或鼠标移动,对方检测到scrollY全程为0,直接弹验证码。

正确做法:

  1. 页面加载完成后,让鼠标从左上角缓慢移到页面中部,再轻轻向下拖动滚动条
  2. 滚动别匀速——先快后慢,中间停顿1–2秒,模拟扫视内容
  3. 在某张图或某段文字上“悬停”2秒,就像你真的被它吸引了一样

为什么同一个代理IP,上午能用下午就被封?

IP本身没问题,问题出在你让它“太勤奋”。

网站后台每天都在画每个IP的行为画像:它访问了几个路径?集中在几点?失败率多少?有没有连续刷同一个接口?一旦某个IP的数据点明显偏离普通用户的分布区间,就会被悄悄拉黑。

一个朋友的翻车经历:
他买了100个住宅IP爬旅游攻略站,前两天很顺,第三天开始IP接连失效。查日志才发现:所有IP都在凌晨2–5点集中开工,而网站真实用户95%的活跃时间是晚上7–11点。相当于100个人同时半夜翻你家窗户——不抓你抓谁?

改进策略:

  • 给每个IP配一个“作息表”:有的安排在中午12点跑,有的放在晚上9点,别全挤在冷门时段
  • 单IP日请求量别超过该网站普通用户日均访问量的2倍(比如用户平均一天点15个页面,你就别让它跑50次)
  • 如果某个IP连续5次返回403或超时,立刻停用,别 retry 到死

如何用“浏览器指纹”反制反爬虫系统?

浏览器指纹就像你的数字胎记——换了IP、清了cookie、重装系统都没用,只要Canvas、WebGL、AudioContext这些底层特征没变,网站就认得出:“又是你。”

它不看你从哪来,只看你“长什么样”。

我能告诉你的现实:
爬一个音乐平台时,我换了IP、改了UA、删了所有本地存储,但每次请求返回的设备ID都一样。最后发现:我用的Docker容器里显卡驱动固定,系统字体列表也一成不变。换成不同基础镜像+随机字体配置后,指纹才真正“变脸”。

可以尝试的手段:

  • puppeteer-extra-plugin-stealth插件,它会自动干扰Canvas指纹生成逻辑
  • 启动浏览器前,用环境变量临时覆盖系统字体(比如Linux下设FONTCONFIG_PATH指向一个含3–5种字体的精简配置)
  • 不要长期只用Chrome 115;隔几天换用Edge 114或Firefox 120,不同内核的指纹差异比你想的大得多

爬虫被验证码卡住时,你该做哪3种尝试?

别急着接打码平台。很多验证码不是“防你”,只是“拦快的”。你慢一点、绕一绕、看一看,往往就过去了。

我试过的3个有效方法:

  1. 暂停一会儿,等它自己撤防:有些验证码是临时风控策略,不是永久标记。你停30–60分钟,换回原IP再试,大概率能过。我遇到Google reCAPTCHA时,就是等了40分钟,再访问就直接进去了。

  2. 走完整浏览路径,别抄近道:验证码常在“非自然路径”上触发。比如你要爬商品页,别直接GET /product/12345,而是先GET首页 → 解析分类链接 → GET分类页 → 解析搜索框 → POST关键词 → 解析结果页 → 最后GET目标商品页。让整个链路看起来像一次真实搜索。

  3. 先看懂验证码在考什么:有些所谓“图形验证码”,其实只是扭曲的数字图。用Tesseract + OpenCV简单二值化+降噪,识别率就能上七成。别一上来就花钱买服务,先确认它是不是真难。

今天就能执行的一个操作步骤

打开你正在调试的爬虫项目,找到控制并发或延时的那几行代码。
现在,别改它们。
打开目标网站的公开Google Analytics实时报告(很多企业官网底部会放GA ID,或直接搜“site:xxx.com analytics”能找到),看看当前在线人数是多少。
然后把你的爬虫并发数,设成这个数字的1%–2%:如果实时在线200人,最多开3–4个并发;如果在线5000人,可以开到50–100个。
记住:你的目标不是最快,而是最不显眼。