PHP项目如何配置站点防爬虫机制?

wen PHP项目 33

本文目录导读:

PHP项目如何配置站点防爬虫机制?

  1. 基础层:robots.txt 规则
  2. 请求频率限制(最核心)
  3. 请求验证层
  4. 高级防护层
  5. Nginx 层防护(推荐)
  6. 综合配置示例
  7. 注意事项

为PHP项目配置防爬虫机制需要综合多种策略,既要有效阻止爬虫,又要避免误伤正常用户(如搜索引擎),以下是分层的配置方案:

基础层:robots.txt 规则

虽然这只是君子协议,但可以约束合规爬虫:

# 禁止所有爬虫访问
User-agent: *
Disallow: /
# 或只允许特定目录
User-agent: *
Allow: /public/
Disallow: /admin/
Disallow: /api/

请求频率限制(最核心)

1 基于 IP 的限流(推荐)

// 使用 Redis 实现滑动窗口限流
function rateLimit($ip, $maxRequests = 60, $timeWindow = 60) {
    $redis = new Redis();
    $redis->connect('127.0.0.1', 6379);
    $key = "ratelimit:{$ip}";
    $current = $redis->get($key);
    if ($current === false) {
        $redis->setex($key, $timeWindow, 1);
        return true;
    }
    if ($current >= $maxRequests) {
        header('HTTP/1.1 429 Too Many Requests');
        exit('请求过于频繁,请稍后再试');
    }
    $redis->incr($key);
    return true;
}
// 调用
rateLimit($_SERVER['REMOTE_ADDR']);

2 基于 User-Agent 过滤

function blockBadBot() {
    $userAgent = $_SERVER['HTTP_USER_AGENT'] ?? '';
    // 常见的爬虫 User-Agent 列表
    $badBots = [
        'AhrefsBot',
        'DotBot',
        'SemrushBot',
        'MJ12bot',
        'BLEXBot',
        'MegaIndex',
        'Python-urllib',
        'Scrapy',
        'curl',
        'wget'
    ];
    foreach ($badBots as $bot) {
        if (stripos($userAgent, $bot) !== false) {
            header('HTTP/1.1 403 Forbidden');
            exit('Access Denied');
        }
    }
}

请求验证层

1 Cookie/Token 验证

// 前端设置一个简单的 JS 验证 cookie
session_start();
if (!isset($_SESSION['verified'])) {
    // 要求前端加载时设置特定 cookie
    if (!isset($_COOKIE['session_verify'])) {
        header('HTTP/1.1 403 Forbidden');
        exit('需要启用 JavaScript');
    }
    $_SESSION['verified'] = true;
}

2 隐藏字段验证(Honeypot)

在表单中添加不可见的输入字段,正常用户不会填写:

// HTML
<input type="text" name="website" style="display:none" tabindex="-1" autocomplete="off">
// PHP 验证
if (!empty($_POST['website'])) {
    // 是爬虫,拒绝请求
    exit('Spam detected');
}

高级防护层

1 IP 黑名单/白名单

function checkIP() {
    $ip = $_SERVER['REMOTE_ADDR'];
    // 代理 IP 处理
    if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
        $ips = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
        $ip = trim(end($ips));
    }
    // 黑名单检查
    $blacklist = ['123.45.67.89', '98.76.54.32'];
    if (in_array($ip, $blacklist)) {
        header('HTTP/1.1 403 Forbidden');
        exit('IP banned');
    }
    // 检查是否来自已知数据中心(爬虫常用)
    $dataCenterIPs = file_get_contents('https://raw.githubusercontent.com/.../datacenter-ips.txt');
    // 实现 IP 范围匹配
}

2 行为分析

class BehaviorAnalyzer {
    private $redis;
    public function analyze() {
        $ip = $_SERVER['REMOTE_ADDR'];
        $sessionId = session_id();
        // 记录访问路径
        $this->redis->lPush("path:{$sessionId}", $_SERVER['REQUEST_URI']);
        // 检查异常行为
        $paths = $this->redis->lRange("path:{$sessionId}", 0, -1);
        // 爬虫特征:短时间内访问大量不同 URL
        if (count($paths) > 100 && time() - $start < 60) {
            $this->blockIP($ip);
        }
        // 检查点击间隔
        $lastVisit = $this->redis->get("lastvisit:{$sessionId}");
        if ($lastVisit && time() - $lastVisit < 0.5) {
            // 间隔小于 0.5 秒,可能是自动化工具
            $this->addWarning($ip);
        }
        $this->redis->setex("lastvisit:{$sessionId}", 3600, time());
    }
}

Nginx 层防护(推荐)

1 限制请求速率

# 在 http 或 server 块中
limit_req_zone $binary_remote_addr zone=one:10m rate=30r/m;
location /api/ {
    limit_req zone=one burst=5 nodelay;
}

2 连接数限制

limit_conn_zone $binary_remote_addr zone=addr:10m;
server {
    location / {
        limit_conn addr 10;
        limit_conn_status 503;
    }
}

3 封锁常见爬虫 User-Agent

# 在 server 块中添加
if ($http_user_agent ~* (AhrefsBot|DotBot|SemrushBot|MJ12bot|curl|wget) ) {
    return 403;
}

综合配置示例

<?php
// 防爬虫入口文件
class AntiCrawler {
    public function run() {
        // 1. 基础 User-Agent 过滤
        $this->blockBadUA();
        // 2. IP 频率限制
        $this->rateLimit();
        // 3. 验证身份
        $this->verifySession();
        // 4. 行为分析
        $this->analyzeBehavior();
    }
    private function blockBadUA() {
        $ua = $_SERVER['HTTP_USER_AGENT'] ?? '';
        $badPatterns = ['python', 'curl', 'wget', 'scrapy', 'httpclient'];
        foreach ($badPatterns as $pattern) {
            if (stripos($ua, $pattern) !== false) {
                http_response_code(403);
                exit('Access denied');
            }
        }
    }
    private function rateLimit() {
        $ip = $_SERVER['REMOTE_ADDR'];
        $cache = new RedisCache();
        $key = "rate:{$ip}";
        $count = $cache->get($key) ?: 0;
        if ($count > 60) { // 每分钟 60 次
            http_response_code(429);
            exit('Rate limit exceeded');
        }
        $cache->increment($key, 60);
    }
}

注意事项

  1. 不要完全封锁搜索引擎:确保 Googlebot、Bingbot 等可通过
  2. 使用 CDN/WAF:CloudFlare、阿里云 WAF 等有内置防爬虫功能
  3. 日志分析:定期分析访问日志,发现异常 IP 加入黑名单
  4. 逐步加强:先提示,再限速,最后封锁

建议组合使用多种方法,并在生产环境前充分测试,避免误伤正常用户。

抱歉,评论功能暂时关闭!