敏感词校验

场景:敏感词存在数据库中,也缓存到redis中,判断评论信息是否包含敏感词。

方案一:用字符串charAt对比。

方案二:DFA算法

由于需求是只要存在敏感词就直接返回是否包含敏感词结果。所以用charAt方法速度快,占用内存小,所以方案一比较适合。

方案二适合,找到包含的所有敏感词,然后将敏感词输出,并替代。效率高。但是敏感词数量与所占内存成正比。

方案一代码:

思路:其实就是一段文字字符串,是否包含敏感词。

/**
	 * 
	 * Desc:(敏感词校验)container是否包含child
	 * @author wangdeqiu
	 * @date 2018年10月18日 下午4:28:41
	 * @param text :要判断的文字信息
	 * @return childWord:敏感词
	 */
	public static boolean str1ContainsStr2(String text, String childWord) {
		if (text.length() < childWord.length()) {
			return false;
		}
		int maxLength = text.length();
		char first = childWord.charAt(0);
		int i = -1;
		while (++i < maxLength) {
			// 第一个是否能找到
			if (first == text.charAt(i)) {
				// 如果找到匹配之后的元素
				if (mathStr(text.substring(i), childWord)) {
					return true;
				}

			}
		}
		return false;
	}

	private static boolean mathStr(String max, String min) {
		if (max.length() < min.length()) {
			return false;
		}
		int i = -1;
		int minLength = min.length();
		while (++i < minLength) {
			if (min.charAt(i) != max.charAt(i)) {
				return false;
			}
		}
		return true;
	}
	

方案二代码:

1.敏感词库初始化(将敏感词用DFA算法的原理封装到敏感词库中,敏感词库采用HashMap保存),代码如下:

package com.haidaipuhui.service.SensitiveWord;

import java.util.*;

/**
 * @author wangdeqiu
 * @date 2018/11/6
 * @Dsecription: 敏感词库初始化
 */
@SuppressWarnings("rawtypes")
public class SensitiveWordInit {

    //敏感词库
    public Map sensitiveWordMap;

    /**
     *@describe:  初始化敏感词
     *@author wangdeqiu
     *@date 2018/11/6 下午1:46
     *@param  sensitiveWords:redis/数据库中获取的敏感词
     *
     */
	public Map initKeyWord(List<String> sensitiveWords){
        try{
            // 从敏感词集合对象中取出敏感词并封装到Set集合中
            Set<String> keyWordSet = new HashSet<String>();
            for(String s:sensitiveWords){
                keyWordSet.add(s.trim());
            }
            //将词库放到hashmap中
            addSensitiveWordToHashMap(keyWordSet);
        }catch(Exception e){
            e.printStackTrace();
        }

        return sensitiveWordMap;
    }


    /**
     *@describe:  封装敏感词库
     *@author wangdeqiu
     *@date 2018/11/6 下午1:47
     *@param  keyWordSet :初始后的敏感词
     *
     */
    @SuppressWarnings("unchecked")
	public void addSensitiveWordToHashMap(Set<String> keyWordSet){
        // 初始化HashMap对象并控制容器的大小
        sensitiveWordMap = new HashMap(keyWordSet.size());
        // 敏感词
        String key = null;
        // 用来按照相应的格式保存敏感词库数据
        Map nowMap = null;
        // 用来辅助构建敏感词库
        Map<String,String> newWorMap = null;
        // 使用一个迭代器来循环敏感词集合
        Iterator<String> iterator = keyWordSet.iterator();
        while (iterator.hasNext()){
            key = iterator.next();
            // 等于敏感词库,HashMap对象在内存中占用的是同一个地址,所以此nowMap对象的变化,sensitiveWordMap对象也会跟着改变
            nowMap = sensitiveWordMap;
            for(int i=0;i<key.length();i++){
                // 截取敏感词当中的字,在敏感词库中字为HashMap对象的Key键值
                char keyChar = key.charAt(i);
                // 判断这个字是否存在于敏感词库中
                Object wordMap = nowMap.get(keyChar);
                if (wordMap != null)
                {
                    nowMap = (Map) wordMap;
                }else{
                    newWorMap = new HashMap<String, String>();
                    newWorMap.put("isEnd", "0");
                    nowMap.put(keyChar, newWorMap);
                    nowMap = newWorMap;
                }
                // 如果该字是当前敏感词的最后一个字,则标识为结尾字
                if (i == key.length() - 1){
                    nowMap.put("isEnd", "1");
                }
                System.out.println("封装敏感词库过程:"+sensitiveWordMap);
            }
            System.out.println("查看敏感词库数据:" + sensitiveWordMap);
        }
    }



}

2.写一个敏感词过滤工具类,里面可以写上自己需要的方法,代码如下

package com.haidaipuhui.service.SensitiveWord;



import java.util.*;

import org.springframework.stereotype.Component;

import com.haidaipuhui.util.SystemUtil;

/**
 * @author wangdeqiu
 * @date 2018/11/6
 * @Dsecription:  敏感词过滤类
 */
@SuppressWarnings("rawtypes")
@Component
public class SensitivewordTool {

    //敏感词库
	public static Map sensitiveWordMap;

    //只过滤最小敏感词 //最小匹配规则,如:敏感词库["中国","中国人"],语句:"我是中国人",匹配结果:我是[中国]人
    public static int minMatchTYpe = 1;
    //过滤所有敏感词 //最大匹配规则,如:敏感词库["中国","中国人"],语句:"我是中国人",匹配结果:我是[中国人]
    public static int maxMatchTYpe = 2;

    /**
     *@describe: 敏感词库敏感词的数量
     *@author wangdeqiu
     *@date 2018/11/6 下午2:02
     *@param
     *
     */
    public static int getWordSize(){
        if(SensitivewordTool.sensitiveWordMap==null){

            return 0;
        }
        return SensitivewordTool.sensitiveWordMap.size();

    }
    
    
    /**
     *@describe: 是否包含敏感词
     *@author wangdeqiu
     *@date 2018/11/6 下午2:04
     *@param 
     * 
     */  

    public static  boolean isContaintSensitiveWord(String txt,int matchType){
        boolean flag = false;
        for(int i=0;i<txt.length();i++){
            int matchFlag = checkSensitiveWord(txt, i, matchType);
            if(matchFlag>0){
                return true;
            }

        }
        return flag;
    }


    /**
     *@describe:   获取敏感词内容
     *@author wangdeqiu
     *@date 2018/11/6 下午2:07
     *@param
     *
     */
    public static Set<String>  getSensitiveWord(String txt,int matchType){
        Set<String> sensitiveWordList = new HashSet<String>();
        for (int i = 0; i < txt.length(); i++)
        {
            int length = checkSensitiveWord(txt, i, matchType);
            if (length > 0)
            {
                // 将检测出的敏感词保存到集合中
                sensitiveWordList.add(txt.substring(i, i + length));
                i = i + length - 1;
            }
        }
        return sensitiveWordList;
    }


    /**
     *@describe:  替换敏感词
     *@author wangdeqiu
     *@date 2018/11/6 下午2:37
     *@param
     *
     */
    public static String replaceSensitiveWord(String txt, int matchType, String replaceChar)
    {
        String resultTxt = txt;
        Set<String> set = getSensitiveWord(txt, matchType);
        Iterator<String> iterator = set.iterator();
        String word = null;
        String replaceString = null;
        while (iterator.hasNext())
        {
            word = iterator.next();
            replaceString = getReplaceChars(replaceChar, word.length());
            resultTxt = resultTxt.replaceAll(word, replaceString);
        }

        return resultTxt;
    }

    /**
     *@describe:  替换敏感词内容
     *@author wangdeqiu
     *@date 2018/11/6 下午2:11
     *@param
     *
     */
    private static String getReplaceChars(String replaceChar, int length)
    {
        String resultReplace = replaceChar;
        for (int i = 1; i < length; i++)
        {
            resultReplace += replaceChar;
        }

        return resultReplace;
    }

    /**
     *@describe:  检查敏感词数量
     *@author wangdeqiu
     *@date 2018/11/6 下午2:11
     *@param
     *
     */
    public static int checkSensitiveWord(String txt,int beginIndex,int matchType){
        boolean flag = false;
        // 记录敏感词数量
        int matchFlag = 0;
        char word = 0;
        Map nowMap = SensitivewordTool.sensitiveWordMap;
        for (int i = beginIndex; i < txt.length(); i++){
            word = txt.charAt(i);
            // 判断该字是否存在于敏感词库中
            nowMap = (Map) nowMap.get(word);
            if (nowMap != null){
                matchFlag++;
                // 判断是否是敏感词的结尾字,如果是结尾字则判断是否继续检测
                if ("1".equals(nowMap.get("isEnd")))
                {
                    flag = true;
                    // 判断过滤类型,如果是小过滤则跳出循环,否则继续循环
                    if (SensitivewordTool.minMatchTYpe == matchType)
                    {
                        break;
                    }
                }
            }else
            {
                break;
            }
        }
        if (!flag)
        {
            matchFlag = 0;
        }
        return matchFlag;

    }

    /**
     * 
     * Desc:敏感词过滤
     * @author wangdeqiu
     * @date 2018年11月7日 下午2:24:25
     * @param
     * @return
     */
    public static  Set<String> sensitiveWordFiltering(String text)
    {
        // 初始化敏感词库对象
        SensitiveWordInit sensitiveWordInit = new SensitiveWordInit();
        // 从数据库中获取敏感词对象集合(调用的方法来自Dao层,此方法是service层的实现类)
        List<String> sensitiveWords =SystemUtil.getWordToRedis();
        // 构建敏感词库
        Map sensitiveWordMap = sensitiveWordInit.initKeyWord(sensitiveWords);
        // 传入SensitivewordEngine类中的敏感词库
        SensitivewordTool.sensitiveWordMap = sensitiveWordMap;
        // 得到敏感词有哪些,传入2表示获取所有敏感词
        Set<String> set = SensitivewordTool.getSensitiveWord(text, 2);
        return set;
    }
    
    /**
     * 
     * Desc:判断是否存在敏感词
     * @author wangdeqiu
     * @date 2018年11月7日 下午2:24:38
     * @param
     * @return
     */
    public static  boolean isExitSensitiveWord(String text)
    {
        // 初始化敏感词库对象
        SensitiveWordInit sensitiveWordInit = new SensitiveWordInit();
        // 从数据库中获取敏感词对象集合(调用的方法来自Dao层,此方法是service层的实现类)
        List<String> sensitiveWords =SystemUtil.getWordToRedis();
        // 构建敏感词库
        Map sensitiveWordMap = sensitiveWordInit.initKeyWord(sensitiveWords);
        // 传入SensitivewordEngine类中的敏感词库
        SensitivewordTool.sensitiveWordMap = sensitiveWordMap;
        // 得到敏感词有哪些,传入1表示获取所有敏感词
        boolean isExit= SensitivewordTool.isContaintSensitiveWord(text, 1);
        return isExit;
    }




}

参考:https://www.jb51.net/article/116752.htm

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值