本文目录导读:

为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);
}
}
注意事项
- 不要完全封锁搜索引擎:确保 Googlebot、Bingbot 等可通过
- 使用 CDN/WAF:CloudFlare、阿里云 WAF 等有内置防爬虫功能
- 日志分析:定期分析访问日志,发现异常 IP 加入黑名单
- 逐步加强:先提示,再限速,最后封锁
建议组合使用多种方法,并在生产环境前充分测试,避免误伤正常用户。