85 lines
3.1 KiB
PHP
85 lines
3.1 KiB
PHP
<?php
|
|
// +----------------------------------------------------------------------
|
|
// | YwxApp [ WE CAN DO IT JUST THINK ]
|
|
// +----------------------------------------------------------------------
|
|
// | Copyright (c) 2026-2036 http://ywxapp.cn All rights reserved.
|
|
// +----------------------------------------------------------------------
|
|
// | Author: ywxapp<admin@ywxapp.cn>
|
|
// +----------------------------------------------------------------------
|
|
declare(strict_types=1);
|
|
|
|
namespace ywxapp\library;
|
|
|
|
/**
|
|
* 搜索引擎蜘蛛识别
|
|
*
|
|
* 仅按 User-Agent 特征串识别(不做 DNS 反查,保证零阻塞)。
|
|
* 新增蜘蛛只需在 SPIDERS 追加一行:标识 => [UA特征串列表, 显示名]。
|
|
*
|
|
* @author ywxapp <admin@ywxapp.cn>
|
|
*/
|
|
class SpiderDetect
|
|
{
|
|
/**
|
|
* 蜘蛛特征表:key=入库标识,value=[UA 特征串(不区分大小写,命中任一即算), 中文显示名]
|
|
*/
|
|
public const SPIDERS = [
|
|
'baidu' => [['Baiduspider'], '百度'],
|
|
'google' => [['Googlebot', 'Google-InspectionTool', 'AdsBot-Google'], '谷歌'],
|
|
'bing' => [['bingbot', 'msnbot', 'BingPreview'], '必应'],
|
|
'sogou' => [['Sogou web spider', 'Sogou inst spider', 'Sogou Pic Spider'], '搜狗'],
|
|
'so360' => [['360Spider', 'HaoSouSpider', 'qihoobot'], '360'],
|
|
'bytedance' => [['Bytespider', 'ToutiaoSpider'], '字节跳动'],
|
|
'shenma' => [['YisouSpider'], '神马'],
|
|
'huawei' => [['PetalBot'], '华为花瓣'],
|
|
'yandex' => [['YandexBot'], 'Yandex'],
|
|
'duckduckgo' => [['DuckDuckBot', 'DuckDuckGo-Favicons-Bot'], 'DuckDuckGo'],
|
|
'yahoo' => [['Yahoo! Slurp'], '雅虎'],
|
|
'apple' => [['Applebot'], '苹果'],
|
|
'gptbot' => [['GPTBot', 'ChatGPT-User', 'OAI-SearchBot'], 'OpenAI'],
|
|
'claudebot' => [['ClaudeBot', 'anthropic-ai'], 'Anthropic'],
|
|
'semrush' => [['SemrushBot'], 'Semrush'],
|
|
'ahrefs' => [['AhrefsBot'], 'Ahrefs'],
|
|
'mj12' => [['MJ12bot'], 'Majestic'],
|
|
'facebook' => [['facebookexternalhit', 'FacebookBot'], 'Facebook'],
|
|
];
|
|
|
|
/**
|
|
* 识别 UA,命中返回蜘蛛标识(SPIDERS 的 key),未命中返回 null
|
|
*/
|
|
public static function detect(string $userAgent): ?string
|
|
{
|
|
if ($userAgent === '') {
|
|
return null;
|
|
}
|
|
foreach (self::SPIDERS as $key => [$needles]) {
|
|
foreach ($needles as $needle) {
|
|
if (stripos($userAgent, $needle) !== false) {
|
|
return $key;
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* 蜘蛛标识 → 中文显示名(未知标识原样返回)
|
|
*/
|
|
public static function label(string $key): string
|
|
{
|
|
return self::SPIDERS[$key][1] ?? $key;
|
|
}
|
|
|
|
/**
|
|
* 全部蜘蛛 标识=>显示名(后台下拉/报表用)
|
|
*/
|
|
public static function labels(): array
|
|
{
|
|
$out = [];
|
|
foreach (self::SPIDERS as $key => [, $label]) {
|
|
$out[$key] = $label;
|
|
}
|
|
return $out;
|
|
}
|
|
}
|