4、IP代理与反代理:IP代理池的构建、代理质量评估、反代理技术

聊到搜索引擎反作弊,IP代理这块是绕不开的硬骨头。我入行那会儿,爬虫工程师和反作弊团队就像猫鼠游戏,而IP代理就是老鼠最常用的隐身衣。说白了,代理池就是你的“马甲库”,但马甲质量好不好,直接决定了你能活多久。

4.1 IP代理池的构建

构建代理池,我习惯分三步走:采集、验证、存储。别一上来就想着搞几百万个IP,没用的。质量比数量重要得多。

第一步:代理来源

  • 免费代理网站:西刺、快代理这些。说实话,免费的质量堪忧,存活率可能不到10%。我建议只用来做测试或低优先级任务。
  • 付费代理服务:比如阿布云、芝麻代理。稳定性好很多,但成本高。我在项目中遇到过,付费代理如果被滥用,照样会被封。
  • 自建代理池:用云服务器搭Squid或TinyProxy。这是最可控的方式,但需要一定的运维成本。

第二步:代理验证

拿到代理后,必须验证。我一般写个脚本,用目标搜索引擎的首页做测试。为什么?因为有些代理能访问百度,但访问谷歌就挂了。验证指标包括:

  • 响应时间(< 3秒算及格)
  • HTTP状态码(200才算活)
  • 是否被目标网站屏蔽(返回验证码或403)

核心要点:验证频率不能太低。我见过有人一天只验证一次,结果大部分IP早就死了,还在傻傻地用。

第三步:存储与调度

我推荐用Redis的有序集合(Sorted Set)来存代理。把响应时间作为分数,这样每次取代理时,能优先拿到最快的。代码大概长这样:

import redis
import requests

r = redis.Redis(host='localhost', port=6379, db=0)

def add_proxy(proxy, latency):
    # 用延迟作为分数,延迟越低排名越高
    r.zadd('proxy_pool', {proxy: latency})

def get_best_proxy():
    # 取出延迟最低的3个代理
    proxies = r.zrange('proxy_pool', 0, 2, withscores=True)
    return proxies

def validate_proxy(proxy):
    try:
        resp = requests.get('https://www.baidu.com', 
                           proxies={'http': proxy, 'https': proxy},
                           timeout=5)
        if resp.status_code == 200:
            return True
    except:
        return False
    return False

避坑指南:我曾经把代理池的过期时间设成24小时,结果半夜爬虫全挂了。后来改成每10分钟验证一次,存活率从30%提升到了85%。

4.2 代理质量评估

评估代理质量,不能只看“能不能用”。我总结了一套评估体系,分为三个维度:

评估维度 指标 合格标准
可用性 存活率、响应时间 存活率>80%,响应时间<2s
匿名性 是否泄露真实IP、是否携带X-Forwarded-For 高匿名代理(不泄露任何信息)
稳定性 连续可用时长、抖动率 连续可用>30分钟,抖动率<20%

你想想看,如果一个代理虽然能用,但每次请求都暴露你的真实IP,那跟裸奔有什么区别?我习惯用 httpbin.org/ip 来检测匿名性,看看返回的IP是不是代理IP。

注意:有些代理会篡改请求头,比如添加奇怪的User-Agent。这种代理千万别用,容易被反作弊系统标记。

4.3 反代理技术

好了,现在站在反作弊的角度,看看怎么防这些代理。说白了,反代理就是让爬虫工程师觉得“这钱花得不值”。

4.3.1 IP黑名单

最基础的手段。把已知的代理IP、数据中心IP加入黑名单。我见过最狠的做法,是把整个云服务商的IP段都封了。嗯,这招确实有效,但误伤也大。

黑名单的维护要动态。我建议用Redis的Set来存,配合过期时间。比如:

def add_to_blacklist(ip, expire_time=3600):
    r.sadd('blacklist', ip)
    r.expire(ip, expire_time)

def is_blacklisted(ip):
    return r.sismember('blacklist', ip)

4.3.2 频率限制

这是反代理的核心。别搞那种“同一个IP每秒最多10次”的简单限制。爬虫工程师会笑出声的。我推荐用滑动窗口算法,结合用户行为特征。

举个例子:

  • 同一个IP,1分钟内请求超过30次,触发验证码
  • 同一个IP,1小时内请求超过200次,直接封24小时
  • 同一个IP,访问路径异常(比如跳过首页直接访问详情页),降低阈值

我的经验:频率限制一定要有“梯度”。第一次违规给警告,第二次弹验证码,第三次才封。直接封杀太粗暴,容易误伤正常用户。

4.3.3 地理位置检测

这个有意思。如果一个IP来自北京,但请求的页面是上海本地生活服务,而且请求时间在凌晨3点……嗯,大概率是爬虫。

我做过一个系统,把IP的地理位置和用户行为做关联分析:

  • IP归属地是否与用户声称的地区一致?
  • 短时间内,IP是否在多个城市之间“瞬移”?
  • IP是否来自数据中心或代理出口节点?

检测数据中心IP,可以用MaxMind的GeoIP数据库,或者直接查IP段的归属。我记得有一次,一个爬虫用了AWS东京的节点,但请求的页面全是中文内容,而且时间戳显示是北京时间下午3点。这种“时区错位”也是明显的异常信号。

小技巧:把地理位置检测和频率限制结合起来。比如,来自数据中心的IP,频率阈值直接降低到普通用户的1/10。这样既减少了误伤,又提高了攻击成本。

最后说一句,反代理没有银弹。你封得越狠,爬虫工程师就越会想办法绕过。我个人的理念是:让攻击成本大于收益,而不是追求100%拦截。毕竟,搜索引擎本身也需要爬虫来抓取内容,对吧?