简介:Crawler-Detect 是一款专为PHP开发者打造的网络爬虫(Bot/Crawler/Spider)精准检测类库,被誉为PHP生态中爬虫检测的事实标准。内置1000+条精准正则规则,远超传统检测方式的50-200条,支持多HTTP头组合验证,内存仅KB级,性能开销极低。提供Composer一键安装,3行代码即可实现爬虫识别,并支持自定义规则扩展、规则缓存、轻量级检测、异步检测等高级优化方案
Crawler-Detect 是一个专注于识别网络爬虫(Bot/Crawler/Spider)的 PHP 类库,通过分析User-Agent字符串和HTTP头信息,实现对各类网络爬虫的精准检测。作为GitHub上星标数超4.5k的开源项目,它已成为PHP生态中爬虫检测的事实标准。
| 特性 | 传统检测方式 | Crawler-Detect |
|---|---|---|
| 规则数量 | 约50-200条 | 1000+条 精准正则 |
| 更新频率 | 手动维护 | 社区驱动 实时更新 |
| 检测维度 | 单一User-Agent | 多HTTP头 组合验证 |
| 性能开销 | 高(全量匹配) | 低(预编译正则) |
| 内存占用 | MB级 | KB级 轻量级 |
| 多语言支持 | 仅限PHP | 15+ 语言端口 |
安装要求很简单,只要PHP版本大于5.3,环境安装了Composer即可
# 方式1:Composer安装(推荐)
composer require jaybizzle/crawler-detect
# 方式2:手动下载
git clone https://link.gitcode.com/i/105cf730c0ec9e1d4c8442da7789a88d.git
<?php
useJaybizzle\CrawlerDetect\CrawlerDetect;
// 初始化检测器
$crawler = new CrawlerDetect();
// 场景1:检测当前请求
if ($crawler->isCrawler()) {
header('HTTP/1.1 403 Forbidden');
exit('爬虫访问被拒绝');
}
// 场景2:检测指定User-Agent
$userAgent = 'Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)';
if ($crawler->isCrawler($userAgent)) {
echo"匹配到爬虫: " . $crawler->getMatches(); // 输出"Googlebot"
}
// 场景3:批量检测日志
$logs = [
'Baiduspider/2.0',
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/98.0.4758.102',
'Sogou web spider/4.0'
];
foreach ($logs as $log) {
echo $log . " => " . ($crawler->isCrawler($log) ? "是爬虫" : "正常用户") . "\n";
}
自定义爬虫规则
当内置规则无法满足特定需求时,可通过以下方式扩展:
<?php
useJaybizzle\CrawlerDetect\CrawlerDetect;
useJaybizzle\CrawlerDetect\Fixtures\Crawlers;
// 扩展内置爬虫规则
class CustomCrawlers extends Crawlers {
protected $data = [
// 新增自定义规则
'^mycustombot\/[0-9]',
'special-crawler',
// 保留原有规则
...parent::$data
];
}
// 使用自定义规则集
$crawler = new CrawlerDetect();
$reflection = new ReflectionClass($crawler);
$property = $reflection->getProperty('crawlers');
$property->setAccessible(true);
$property->setValue($crawler, new CustomCrawlers());
// 现在可以检测自定义爬虫了
var_dump($crawler->isCrawler('mycustombot/1.0')); // bool(true)
对于高流量网站,建议采用以下优化措施:
// 1. 规则缓存(适用于单进程环境)
$compiledRegex = apc_fetch('crawler_detect_regex');
if (!$compiledRegex) {
$crawler = new CrawlerDetect();
$compiledRegex = $crawler->compileRegex($crawler->crawlers->getAll());
apc_store('crawler_detect_regex', $compiledRegex, 86400); // 缓存24小时
}
// 2. 轻量级检测(仅核心规则)
class LightweightCrawlers extends Crawlers {
protected $data = [
// 仅保留TOP 100常见爬虫规则
'googlebot',
'bingbot',
'baiduspider',
// ...其他核心规则
];
}
// 3. 异步检测(适用于非关键路径)
function asyncDetectCrawler($userAgent) {
$pid = pcntl_fork();
if ($pid == 0) {
$crawler = new CrawlerDetect();
$result = $crawler->isCrawler($userAgent) ? 1 : 0;
file_put_contents("/tmp/crawler_".getmypid().".log", $result);
exit();
}
}
通过Crawler-Detect分析服务器日志,统计爬虫访问情况:
<?php
// 分析Nginx日志
$logFile = '/var/log/nginx/access.log';
$crawler = new CrawlerDetect();
$stats = [
'total' => 0,
'crawlers' => 0,
'top_crawlers' => [],
'hours' => array_fill(0, 24, 0)
];
$handle = fopen($logFile, 'r');
while (($line = fgets($handle)) !== false) {
$stats['total']++;
// 提取User-Agent(假设日志格式包含UA)
preg_match('/"([^"]+)"$/',$line,$matches);
if (empty($matches[1])) continue;
$userAgent = $matches[1];
if ($crawler->isCrawler($userAgent)) {
$stats['crawlers']++;
$botName = $crawler->getMatches();
// 统计TOP爬虫
$stats['top_crawlers'][$botName] = ($stats['top_crawlers'][$botName] ?? 0) + 1;
// 按小时统计
$hour = date('H', strtotime(explode(' [', $line)[1]));
$stats['hours'][$hour]++;
}
}
fclose($handle);
// 输出统计结果
echo"总访问量: {$stats['total']}\n";
echo"爬虫访问量: {$stats['crawlers']} (".round($stats['crawlers']/$stats['total']*100,2)."%)\n";
echo"TOP 5爬虫:\n";
arsort($stats['top_crawlers']);
foreach (array_slice($stats['top_crawlers'], 0, 5) as $bot => $count) {
echo"- $bot: $count次\n";
}
根据爬虫类型实施差异化限制:
<?php
$crawler = new CrawlerDetect();
if ($crawler->isCrawler()) {
$botName = strtolower($crawler->getMatches());
// 搜索引擎爬虫:正常访问,但限制频率
if (in_array($botName, ['googlebot', 'bingbot', 'baiduspider'])) {
$limitKey = "crawler_{$botName}_".$_SERVER['REMOTE_ADDR'];
$count = redis()->incr($limitKey);
redis()->expire($limitKey, 60); // 1分钟窗口
if ($count > 30) { // 每分钟最多30次请求
header('HTTP/1.1 429 Too Many Requests');
exit('Crawler rate limit exceeded');
}
}
// 恶意爬虫:直接阻止
elseif (in_array($botName, ['semrush', 'ahrefsbot', 'mj12bot'])) {
header('HTTP/1.1 403 Forbidden');
exit('Access denied');
}
// 未知爬虫:延迟响应
else {
sleep(3); // 延迟3秒
}
}
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 误判率高 | User-Agent伪装 | 结合IP、行为特征多维度验证 |
| 规则更新不及时 | 爬虫UA不断变化 | 启用自动更新或订阅规则变更 |
| 性能开销大 | 正则匹配复杂 | 实施规则分级、结果缓存 |
| 内存占用高 | 规则集过大 | 使用轻量级规则子集 |
| 无法检测无头浏览器 | 无头浏览器UA接近真实浏览器 | 结合Canvas指纹、字体渲染检测 |