Appearance
爬虫总来抓数据?用IP特征把它们挡在门外
做网站的,基本都遇到过这糟心事:后台日志里一个IP一天访问了几万次,全是抓数据的爬虫。数据被扒走是小,把服务器打挂、拖慢正常用户是大。
这篇讲讲怎么用IP特征做反爬的第一道防线。记住,IP拦截只是防线之一,不是全部,但它成本最低、见效最快。
爬虫长什么样
爬虫和真人的区别,用IP看很清晰:
| 特征 | 真人 | 爬虫 |
|---|---|---|
| 访问频率 | 低,有思考间隔 | 高,机器速度 |
| IP类型 | 家庭宽带(ISP) | 常常是机房(IDC) |
| 归属地 | 和用户一致 | 常和业务无关 |
| 访问模式 | 随机页面 | 按目录规律抓取 |
第一招:频率封禁
最基础也最有效。统计每个IP单位时间内的请求数,超了就封:
python
import time
from collections import defaultdict
requests_per_ip = defaultdict(list)
BAN_TIME = 3600 # 封1小时
def check_rate(ip):
now = time.time()
# 只保留最近1分钟
requests_per_ip[ip] = [t for t in requests_per_ip[ip] if now - t < 60]
requests_per_ip[ip].append(now)
if len(requests_per_ip[ip]) > 60: # 每分钟超过60次
return True
return False注意:这个判断要在所有请求的入口做,别漏了静态资源路径,爬虫可不会只抓HTML。
第二招:机房IP识别
很多爬虫跑在云服务器上,IP是IDC机房类型。真人用户几乎不会用机房IP上网。所以:
python
def is_datacenter(ip):
info = query_ip(ip) # 查IP9
if not info:
return False
return info.get("ip_type") == "IDC"对IDC类型的IP,可以降级处理:限制访问频率、要求验证码、或者直接拒绝。
但要小心:企业专线(BUS)和部分家庭宽带也可能被误判,所以建议是"IDC降低权限",而不是"见IDC就封"。
第三招:行为 + IP组合
光看IP不够,爬虫也会伪装。组合起来更稳:
python
def is_crawler(ip, path_pattern, user_agent):
# 命中1个以上特征就标记
score = 0
if check_rate(ip):
score += 2
if is_datacenter(ip):
score += 2
if "spider" in user_agent.lower() or "bot" in user_agent.lower():
score += 3
if path_pattern == "sequential": # 页面访问有规律
score += 1
return score >= 3封禁的正确姿势
别一上来就永久封,容易误伤(比如整个公司共享一个出口IP)。分层处理:
- 轻度:弹验证码(真人能过,脚本过不了);
- 中度:限速(只允许低频访问);
- 重度:封IP一段时间,并记录。
python
def handle_crawler(ip, level):
if level == "light":
require_captcha(ip)
elif level == "medium":
throttle(ip, rate=1) # 每秒1次
else:
ban_ip(ip, seconds=3600)别忘了这些细节
1. 代理和CDN:如果你挂了CDN,看到的全是CDN节点IP,会误封一片。记得从 X-Forwarded-For 取真实IP。
2. 动态IP的宽大处理:家庭宽带的IP是动态的,可能一晚上换好几个。如果你封了某个ISP IP,可能误伤换了IP的真人。所以对ISP类型的IP,封禁要谨慎。
3. 黑白名单:谷歌、必应等搜索爬虫,UA白名单放行,别跟它们对着干——你还指望它们收录呢。
说点实在的
反爬是场拉锯战,IP特征能挡住大部分"笨爬虫",聪明的爬虫会用代理池、会模拟真人,这时候就得靠验证码、行为检测、甚至风控模型了。但作为第一道防线,IP频率 + 机房识别的组合,性价比已经很高,值得先做。
用到的接口:https://www.ip9.com.cn