本文目录导读:

- 方案一:基于关键词与正则表达式的本地过滤(免费、适合基础敏感词屏蔽)
- 方案二:调用第三方云内容审核API(推荐、成本可控、高准确率)
- 方案三:实现完整的人工审核工作流(后台管理)
- 方案四:针对图片/视频内容的审核
- 总结:如何选择?
在 PHP 项目中实现内容审核功能,通常有三种主流路径:基于关键词的本地过滤、调用第三方云服务 API(如阿里云、百度AI、腾讯云)以及构建本地 AI 模型(难度最大,适合高级场景)。
下面是一个从简单到复杂、从低成本到高精度的完整实现方案。
基于关键词与正则表达式的本地过滤(免费、适合基础敏感词屏蔽)
这是最基础、成本最低的方案,适合屏蔽明确的脏话、广告词或违禁词。
数据结构设计(MySQL)
CREATE TABLE `sensitive_words` ( `id` int(11) NOT NULL AUTO_INCREMENT, `word` varchar(100) NOT NULL COMMENT '敏感词', `word_type` tinyint(1) DEFAULT '1' COMMENT '1=政治, 2=色情, 3=广告', `status` tinyint(1) DEFAULT '1' COMMENT '1启用 0禁用', `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `word` (`word`) ) ENGINE=InnoDB;
PHP 敏感词过滤类
class SensitiveFilter {
private $dict = [];
private $config = [];
public function __construct() {
// 加载敏感词库(建议使用Redis缓存,避免每次查询数据库)
$this->loadDictFromCache();
}
/**
* 检测文本是否包含敏感词
* @param string $text
* @return array ['hit' => true/false, 'words' => [...], 'text' => '过滤后的文本']
*/
public function check($text) {
$hitWords = [];
$filteredText = $text;
// 遍历敏感词进行匹配(优化:使用Trie树实现DFA算法性能更好)
foreach ($this->dict as $word) {
if (mb_stripos($text, $word) !== false) {
$hitWords[] = $word;
// 替换为星号(在实际审核中可能不替换,而是标记待审)
$filteredText = str_ireplace($word, '**', $filteredText);
}
}
return [
'hit' => !empty($hitWords),
'words' => array_unique($hitWords),
'text' => $filteredText
];
}
private function loadDictFromCache() {
// 从Redis或文件读取敏感词列表
$this->dict = ['傻逼', '操你妈', '赌博', '毒品']; // 示例
}
}
在业务逻辑中使用
$content = $_POST['content'];
$filter = new SensitiveFilter();
$result = $filter->check($content);
if ($result['hit']) {
// 方案A:直接拦截并提示用户(适合论坛发帖)
throw new \Exception('含有违禁词:' . implode(',', $result['words']));
// 方案B:自动将其状态设为待审核(更适合CMS、新闻系统)
$contentModel->saveWithStatus($content, 'pending_review');
}
局限性:无法识别拼音变体、谐音(如“草泥马”)、图片中的文字、上下文语义(“我买了一个毒品”vs“吸毒有害健康”)。
调用第三方云内容审核API(推荐、成本可控、高准确率)
这是目前大多数商业项目采用的最佳实践,只需调用HTTP接口,云服务商会自动识别涉政、色情、辱骂、广告等。
主流服务商对比
| 服务商 | 免费额度( | 文档地址 | 特点 |
|---|---|---|---|
| 阿里云 | 每月1000次免费 | 文档 | 支持文本、图片、视频、语音 |
| 百度AI | 每天5万次免费 | 文档 | 有专门的文本审核接口 |
| 腾讯云 | 每月1万次免费 | 文档 | 支持多语言、表情包 |
| 网易易盾 | 1万次/天 | 文档 | 游戏行业常用 |
示例:阿里云文本审核(PHP实现)
安装SDK
composer require alibabacloud/sdk
审核类(建议封装成Service)
use AlibabaCloud\Client\AlibabaCloud;
use AlibabaCloud\Client\Exception\ClientException;
use AlibabaCloud\Client\Exception\ServerException;
class ContentModerationService {
private $accessKeyId;
private $accessKeySecret;
public function __construct() {
$this->accessKeyId = 'your-access-key-id';
$this->accessKeySecret = 'your-access-key-secret';
AlibabaCloud::accessKeyClient($this->accessKeyId, $this->accessKeySecret)
->regionId('cn-shanghai')
->asDefaultClient();
}
/**
* 审核文本内容
* @param string $text
* @param string $userId 用户ID(用于关联审核记录)
* @return array ['pass'=>true/false, 'label'=>'', 'suggestion'=>'', 'riskLevel'=>'']
*/
public function checkText($text, $userId = null) {
try {
$result = AlibabaCloud::green()
->v20220302()
->textModeration()
->withService('nickname_detection') // 使用昵称检测服务,还可选 'comment_detection'
->withServiceParameters(json_encode([
'content' => $text,
'userId' => $userId
]))
->request();
$data = $result->toArray();
// 解析返回结果
if (isset($data['Data']['Results'])) {
$ext = $this->parseResult($data['Data']['Results']);
return $ext;
}
// 默认通过
return ['pass' => true, 'label' => 'normal', 'suggestion' => 'pass', 'riskLevel' => 'none'];
} catch (ClientException $e) {
// Log error
return ['pass' => false, 'error' => $e->getErrorMessage()];
} catch (ServerException $e) {
return ['pass' => false, 'error' => $e->getErrorMessage()];
}
}
private function parseResult($results) {
foreach ($results as $result) {
$label = $result['Label'] ?? '';
$suggestion = $result['Suggestion'] ?? 'pass';
$riskLevel = $result['RiskLevel'] ?? 'low';
if ($suggestion === 'block') {
// 高风险,需拦截
return ['pass' => false, 'label' => $label, 'suggestion' => 'block', 'riskLevel' => $riskLevel];
} elseif ($suggestion === 'review') {
// 疑似违规,需人工审核
return ['pass' => 'review', 'label' => $label, 'suggestion' => 'review', 'riskLevel' => $riskLevel];
}
}
// 全部通过
return ['pass' => true, 'label' => 'normal', 'suggestion' => 'pass', 'riskLevel' => 'low'];
}
}
业务调用与异步审核策略
public function storeComment(Request $request) {
$commentText = $request->input('content');
$moderation = new ContentModerationService();
$result = $moderation->checkText($commentText);
if ($result['pass'] === false) {
// 明确违规:直接拒绝并提示
return response()->json(['code' => 403, 'msg' => '内容包含违规信息', 'detail' => $result['label']]);
} elseif ($result['pass'] === 'review') {
// 疑似违规:保存为草稿,进入人工审核队列
$comment = Comment::create([
'content' => $commentText,
'status' => 'pending_review', // 待审状态
'risk_label' => $result['label']
]);
// 发送通知给管理员
return response()->json(['code' => 200, 'msg' => '提交成功,等待审核']);
} else {
// 通过
$comment = Comment::create([
'content' => $commentText,
'status' => 'active'
]);
return response()->json(['code' => 200, 'msg' => '发布成功']);
}
}
实现完整的人工审核工作流(后台管理)
使用API只能完成机器审核,大多数合规系统需要多级审核流程。
数据库设计(审核记录表)
CREATE TABLE `audit_records` ( `id` int(11) NOT NULL AUTO_INCREMENT, `resource_type` varchar(50) NOT NULL COMMENT '资源类型: article/comment/image/user', `resource_id` int(11) NOT NULL COMMENT '原始资源ID', `content_snapshot` text COMMENT '内容快照(防止原始内容被修改)', `machine_label` varchar(50) DEFAULT NULL COMMENT '机器审核标签', `machine_risk_level` varchar(20) DEFAULT NULL COMMENT '机器风险等级: high/middle/low', `human_reviewer` int(11) DEFAULT NULL COMMENT '人工审核员ID', `human_status` tinyint(1) DEFAULT '0' COMMENT '0未审 1通过 2驳回 3忽略', `audit_remark` varchar(500) DEFAULT NULL COMMENT '审核备注', `audited_at` datetime DEFAULT NULL COMMENT '审核时间', `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `idx_resource` (`resource_type`,`resource_id`), KEY `idx_status` (`human_status`), KEY `idx_machine_status` (`machine_risk_level`) ) ENGINE=InnoDB;
管理员审核后台(Laravel示例)
// 审核列表页
$pendingItems = AuditRecord::where('human_status', 0)
->orderBy('created_at', 'asc')
->paginate(20);
// 审核通过
public function approve($id) {
$record = AuditRecord::findOrFail($id);
$record->human_status = 1; // 通过
$record->human_reviewer = auth()->id();
$record->audited_at = now();
$record->save();
// 更新原始资源状态
$resourceClass = $this->getResourceClass($record->resource_type);
$resource = $resourceClass::find($record->resource_id);
$resource->status = 'active';
$resource->save();
// 记录操作日志
return redirect()->back()->with('success', '审核通过');
}
// 审核驳回
public function reject(Request $request, $id) {
$request->validate(['reason' => 'required|string|max:500']);
$record = AuditRecord::findOrFail($id);
$record->human_status = 2; // 驳回
$record->human_reviewer = auth()->id();
$record->audit_remark = $request->input('reason');
$record->audited_at = now();
$record->save();
// 通知内容发布者
$this->notifyUser($record, 'rejected', $request->input('reason'));
return redirect()->back()->with('success', '已驳回');
}
自动处理策略(定时任务/队列)
// 每天凌晨清理超过7天的待审核数据
$schedule->call(function () {
AuditRecord::where('human_status', 0)
->where('created_at', '<', now()->subDays(7))
->update(['human_status' => 3]); // 自动忽略
})->daily();
针对图片/视频内容的审核
审核不止是文本,以下以图片审核为例(调用阿里云):
public function checkImage($imagePath) {
try {
$result = AlibabaCloud::green()
->v20220302()
->imageModeration()
->withService('baselineCheck') // 基线检测
->withServiceParameters(json_encode([
'imageUrl' => $imagePath,
'dataId' => uniqid()
]))
->request();
$data = $result->toArray();
// 解析结果... 类似文本审核的流程
} catch (\Exception $e) {
Log::error('图片审核失败: ' . $e->getMessage());
return ['pass' => true]; // 审核失败时,默认通过(或拦截)
}
}
如何选择?
| 场景 | 推荐方案 | 成本 |
|---|---|---|
| 个人博客、小型社区,流量<1000/天 | 方案一(关键词过滤) | 0元,需维护词库 |
| 中型社区、电商评论、UGC内容平台 | 方案二(云API)+ 人工审核 | 每月几百~几千元 |
| 短视频/直播平台(视频+音频审核) | 方案二(腾讯/阿里云) | 按量计费,较高 |
| 金融/政府/医疗行业(需极高准确率) | 云API + 本地AI模型 + 多级人工审核 | 高,需专业团队 |
最佳实践建议:
- 前端配合:用户输入时就调用本地过滤(防抖)快速提示,节省API调用成本。
- 用户分级:高信用用户可直接通过,低信用用户触发机器+人工双重审核。
- 缓存结果:同一段内容如果多人发布(如引用新闻),可缓存审核结果。
- 日志留存:所有审核记录保留至少6个月(法规要求)。
如果你需要具体的某个服务商的SDK封装代码(例如阿里云、腾讯云),我可以继续帮你写完整的封装类。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播