PHP项目怎么实现内容审核功能?

wen PHP项目 9

本文目录导读:

PHP项目怎么实现内容审核功能?

  1. 方案一:基于关键词与正则表达式的本地过滤(免费、适合基础敏感词屏蔽)
  2. 方案二:调用第三方云内容审核API(推荐、成本可控、高准确率)
  3. 方案三:实现完整的人工审核工作流(后台管理)
  4. 方案四:针对图片/视频内容的审核
  5. 总结:如何选择?

在 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模型 + 多级人工审核 高,需专业团队

最佳实践建议:

  1. 前端配合:用户输入时就调用本地过滤(防抖)快速提示,节省API调用成本。
  2. 用户分级:高信用用户可直接通过,低信用用户触发机器+人工双重审核。
  3. 缓存结果:同一段内容如果多人发布(如引用新闻),可缓存审核结果。
  4. 日志留存:所有审核记录保留至少6个月(法规要求)。

如果你需要具体的某个服务商的SDK封装代码(例如阿里云、腾讯云),我可以继续帮你写完整的封装类。

抱歉,评论功能暂时关闭!