一、为什么要搭黑白名单
跨境自动化项目里,代理 IP 质量参差不齐,且质量是动态变化的:
- 某个 IP 今天正常,明天进入平台风控名单;
- 同网段被标记,整个段连带风险;
- 手写死一个 "好 IP 列表",过几天就失效。
如果每次都用人工判断哪个 IP 能用,效率低还滞后。正确做法是搭一套自动化的黑白名单体系:根据请求结果自动给 IP 打标签,坏 IP 自动进黑名单并剔除,好 IP 进入白名单优先复用,实现 "越用越准"。
核心价值:
- 封号前提前拦截:坏 IP 在触发风控前就被标记剔除;
- 减少无效请求:避免反复用坏 IP 重试,浪费资源;
- 动态自适应:IP 池质量随使用自动更新,不用人工维护。
二、体系整体设计
2.1 三层名单结构
表格
| 名单 | 定义 | 行为 |
|---|---|---|
| 白名单 | 多次请求稳定成功,无风控信号 | 优先分配,降低任务失败率 |
| 灰名单 | 偶发异常,暂不确定 | 降权,减少分配,持续观察 |
| 黑名单 | 触发风控 / 连续失败 / 网段被标记 | 立即剔除,不再分配 |
2.2 打分模型(动态更新)
每个 IP 维护一个信誉分,根据行为动态增减:
初始分:50
请求成功:+2
请求失败(超时/重置,可恢复):-5
触发风控(403/验证码/封号提示):-30
连续N次失败:直接拉黑
- 分数 ≥ 70:白名单,优先复用
- 40 ~ 70:灰名单,降权观察
- < 40 或触发硬性风控:黑名单,剔除
关键点:风控信号(403 / 验证码)要扣大分,这类信号代表 IP 已被平台盯上,比单纯超时严重得多。
三、Python 实现:IP 信誉管理 + 名单更新
import json
import time
class ProxyPool:
def __init__(self, file_path="proxy_pool.json"):
self.file_path = file_path
self.ips = {} # ip -> {score, state, fail_count, last_update}
self._load()
def _load(self):
try:
with open(self.file_path, "r") as f:
self.ips = json.load(f)
except Exception:
self.ips = {}
def _save(self):
with open(self.file_path, "w") as f:
json.dump(self.ips, f, ensure_ascii=False, indent=2)
def register(self, ip):
"""新IP进池,初始分50"""
if ip not in self.ips:
self.ips[ip] = {"score": 50, "state": "GRAY", "fail_count": 0,
"last_update": time.time()}
def update(self, ip, success=True, risk=False):
"""根据请求结果更新信誉分和名单"""
if ip not in self.ips:
self.register(ip)
item = self.ips[ip]
if risk: # 触发风控,扣大分
item["score"] -= 30
item["fail_count"] += 1
elif success: # 成功加分,重置失败计数
item["score"] += 2
item["fail_count"] = 0
else: # 普通失败(超时/重置)
item["score"] -= 5
item["fail_count"] += 1
# 连续失败强制拉黑
if item["fail_count"] >= 3 or item["score"] <= 0:
item["state"] = "BLACK"
elif item["score"] >= 70:
item["state"] = "WHITE"
else:
item["state"] = "GRAY"
item["last_update"] = time.time()
# 分数封顶100,防止无限累加
item["score"] = min(item["score"], 100)
self._save()
def get_proxy(self, mode="auto"):
"""按模式取IP:auto优先白名单"""
candidates = []
for ip, item in self.ips.items():
if item["state"] == "BLACK":
continue # 黑名单跳过
if mode == "white" and item["state"] != "WHITE":
continue
candidates.append((ip, item["score"]))
if not candidates:
return None
# 按分数从高到低排序,优先高信誉
candidates.sort(key=lambda x: x[1], reverse=True)
return candidates[0][0]
def remove_black(self, ip):
"""手动/自动剔除黑名单IP"""
if ip in self.ips and self.ips[ip]["state"] == "BLACK":
del self.ips[ip]
self._save()
# 使用示例
if __name__ == "__main__":
pool = ProxyPool()
pool.register("1.1.1.1")
pool.register("8.8.8.8")
# 模拟:1.1.1.1 触发风控
pool.update("1.1.1.1", success=False, risk=True)
# 模拟:8.8.8.8 连续成功
for _ in range(5):
pool.update("8.8.8.8", success=True)
print("当前可用IP:", pool.get_proxy())
print("IP池状态:", pool.ips)
四、关键规则细化
4.1 什么信号进黑名单(硬性规则)
以下任一触发,直接拉黑,不靠分数:
- 返回 403 / 触发验证码 / 出现封号提示
- 同网段(如 /24)多个 IP 被风控,整个段降级
- 连续 3 次连接失败(超时、重置、握手失败)
- IP 信誉库(ipinfo/abuseipdb)检测为高风险段
4.2 白名单的 "过期" 问题
白名单 IP 不能永久白。建议:
- 白名单 IP 定期(如 24h)重新探测,过期自动降级为灰名单;
- 动态住宅 IP 本身会轮换,白名单要绑定 "当前会话 IP",会话结束即失效。
4.3 黑白名单与账号 / IP 隔离联动
- 一个 IP 被黑,不要连坐所有账号,但要把该 IP 下运行的账号做风控排查;
- 高权重账号只走白名单 IP,普通采集任务可用灰名单 IP,分级分配。
五、工程落地避坑
- 别把 "超时" 当风控直接拉黑 超时可能是链路抖动,一次超时就拉黑会把好 IP 误杀。用 "连续失败次数" 判断,单次失败只降分。
- 黑白名单状态要持久化 脚本重启后 IP 池状态会丢失,务必落盘(JSON / 数据库),跨进程共享。
- 加分要克制 一次成功 + 2,避免某个 IP 分数虚高;风控扣分要狠(-30),让风险 IP 快速出局。
- 监控 + 告警联动 IP 池黑名单数量激增(如瞬间 10 个 IP 进黑名单),可能是平台风控收紧或代理商整批 IP 被标记,要触发告警,而不是默默剔除。
- 和熔断机制配合 上一篇文章的熔断器管 "单次任务的持续故障",黑白名单管 "IP 池的长期信誉",两者配合:熔断管短期,黑白名单管长期。
六、总结
代理 IP 黑白名单体系,本质是把 "人工判断 IP 好不好" 变成 "系统自动打分、动态标记"。核心设计:
- 三层名单 (白 / 灰 / 黑)+ 信誉分动态增减;
- 风控信号扣大分,连续失败强制拉黑;
- 状态持久化,与熔断、账号隔离联动;
- 监控黑名单激增,识别平台风控收紧。
这套体系能让 IP 池 "越用越准",坏 IP 提前剔除,有效减少因复用风控 IP 导致的批量封号。