1、需求背景

  • 内容审核

内容审核不能过滤一些敏感词:私人侦探、针孔摄象、信用卡提现、广告代理、代开发票、刻章办、出售答案、小额贷款…

需要自己维护一套敏感词,在内容审核的时候,需要验证文章是否包含这些敏感词

2、敏感词-过滤

  • 技术选型
方案说明
数据库模糊查询效率太低
String.indexOf("")查找数据库量大的话也是比较慢
全文检索分词再匹配
DFA算法确定有穷自动机(一种数据结构)

3、DFA实现原理

https://www.cnblogs.com/twoheads/p/11349541.html

DFA全称为:Deterministic Finite Automaton,即确定有穷自动机。

存储:一次性的把所有的敏感词存储到了多个map中,就是下图表示这种结构

敏感词:冰毒、大麻、大坏蛋

1-DFA.png

  • 检索过程

2-DFA.png

4、简单应用

  • 创建数据表和对应实体类,用于维护敏感词库
/**
 * <p>
 * 敏感词信息表
 * </p>
 *
 * @author leaflei
 */
@Data
@TableName("sensitive")
public class WmSensitive implements Serializable {

    private static final long serialVersionUID = 1L;

    /**
     * 主键
     */
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;

    /**
     * 敏感词
     */
    @TableField("sensitives")
    private String sensitives;

    /**
     * 创建时间
     */
    @TableField("created_time")
    private Date createdTime;

}
  • 使用

    @Autowired
    private WmSensitiveService sensitiveService;

   /**
     * DFA本地审核文本内容
     * @param wmNews 文章数据
     * @param allText 文本内容
     * @return 审核结果
     */
    private boolean dfaAuditText(WmNews wmNews, String allText) {
        // 2.1 查询全部敏感词
        List<WmSensitive> wmSensitiveList = wmSensitiveService.list(Wrappers
                .<WmSensitive>lambdaQuery()
                .select(WmSensitive::getSensitives));
        // 过滤,获取敏感词组成的集合
        List<String> sensitiveList = wmSensitiveList.stream().map(WmSensitive::getSensitives).collect(Collectors.toList());
        // 2.2 初始化DFA词库x
        SensitiveWordUtil.initMap(sensitiveList);
        // 2.3 检测文本
        Map<String, Integer> result = SensitiveWordUtil.matchWords(allText);
        // 2.4 根据map结果处理
        if (result.size() > 0) {
            // 审核失败,返回false
           return false;
        }
        // 审核通过,返回true
        return true;
    }