feat(round-16): AI意图情绪分析/展会名片双向互换/雷达爬虫清洗/离线多媒体缓存 (103套件1101测试全绿)

这个提交包含在:
wikiboss
2026-09-21 02:17:06 +08:00
父节点 e6d06f762c
当前提交 8c003b70cd
共有 8 个文件被更改,包括 805 次插入 和 0 次删除

查看文件

@@ -0,0 +1,102 @@
import { Provide } from '@midwayjs/core';
import { BaseService } from '@cool-midway/core';
export type BotClassification = 'SEARCH_CRAWLER' | 'SOCIAL_PREVIEW' | 'SCRIPTER';
export interface BotDetectResult {
isBot: boolean;
botType?: BotClassification;
botName?: string;
}
export interface TrafficFilterResult {
isBot: boolean;
category: 'HUMAN' | 'CRAWLER' | 'SUSPICIOUS_SPAM';
shouldRecordLead: boolean;
reason?: string;
}
const SEARCH_BOTS = ['googlebot', 'bingbot', 'baiduspider', 'yandexbot', 'duckduckbot', 'sogou'];
const SOCIAL_BOTS = ['whatsapp', 'twitterbot', 'facebookexternalhit', 'linkedinbot', 'telegrambot', 'slackbot'];
const SCRIPT_BOTS = ['curl', 'wget', 'python-requests', 'postman', 'httpclient', 'scrapy', 'axios'];
/**
* 基于 User-Agent 识别机器人与爬虫
*/
export function detectBotUserAgent(userAgent?: string): BotDetectResult {
if (!userAgent || typeof userAgent !== 'string') {
return { isBot: false };
}
const ua = userAgent.toLowerCase();
for (const bot of SEARCH_BOTS) {
if (ua.includes(bot)) {
return { isBot: true, botType: 'SEARCH_CRAWLER', botName: bot };
}
}
for (const bot of SOCIAL_BOTS) {
if (ua.includes(bot)) {
return { isBot: true, botType: 'SOCIAL_PREVIEW', botName: bot };
}
}
for (const bot of SCRIPT_BOTS) {
if (ua.includes(bot)) {
return { isBot: true, botType: 'SCRIPTER', botName: bot };
}
}
return { isBot: false };
}
/**
* 检测 1 秒内的频次是否异常超高
*/
export function isRateLimitSuspicious(timestamps: number[], thresholdPerSec = 10): boolean {
if (!timestamps || timestamps.length < thresholdPerSec) {
return false;
}
const sorted = [...timestamps].sort((a, b) => a - b);
const now = sorted[sorted.length - 1];
const countInLastSecond = sorted.filter(t => now - t <= 1000).length;
return countInLastSecond >= thresholdPerSec;
}
/**
* 访客雷达异常流量与爬虫清洗过滤服务
*/
@Provide()
export class RadarBotFilterService extends BaseService {
async filterIncomingTraffic(input: {
ip: string;
userAgent: string;
recentTimestamps?: number[];
}): Promise<TrafficFilterResult> {
const botCheck = detectBotUserAgent(input.userAgent);
if (botCheck.isBot) {
return {
isBot: true,
category: 'CRAWLER',
shouldRecordLead: false,
reason: `检测到 ${botCheck.botType}: ${botCheck.botName}`,
};
}
if (input.recentTimestamps && isRateLimitSuspicious(input.recentTimestamps)) {
return {
isBot: true,
category: 'SUSPICIOUS_SPAM',
shouldRecordLead: false,
reason: '1秒内突发异常高频请求,疑似自动化刷量攻击',
};
}
return {
isBot: false,
category: 'HUMAN',
shouldRecordLead: true,
};
}
}