[Java Web]敏感词过滤算法

1.DFA算法

DFA算法的原理可以参考这里,简单来说就是通过Map构造出一颗敏感词树,树的每一条由根节点到叶子节点的路径构成一个敏感词,例如下图:

代码简单实现如下:

public class TextFilterUtil {

    //日志
    private static final Logger LOG = LoggerFactory.getLogger(TextFilterUtil.class);
    //敏感词库
    private static HashMap sensitiveWordMap = null;
    //默认编码格式
    private static final String ENCODING = "gbk";
    //敏感词库的路径
    private static final InputStream in = TextFilterUtil.class.getClassLoader().getResourceAsStream("sensitive/keyWords.txt");

    /**
     * 初始化敏感词库
     */
    private static void init() {
        //读取文件
        Set<String> keyWords = readSensitiveWords();
        //创建敏感词库
        sensitiveWordMap = new HashMap<>(keyWords.size());
        for (String keyWord : keyWords) {
            createKeyWord(keyWord);
        }
    }

    /**
     * 构建敏感词库
     *
     * @param keyWord
     */
    private static void createKeyWord(String keyWord) {
        if (sensitiveWordMap == null) {
            LOG.error("sensitiveWordMap 未初始化!");
            return;
        }
        Map nowMap = sensitiveWordMap;
        for (Character c : keyWord.toCharArray()) {
            Object obj = nowMap.get(c);
            if (obj == null) {
                Map<String, Object> childMap = new HashMap<>();
                childMap.put("isEnd", "false");
                nowMap.put(c, childMap);
                nowMap = childMap;
            } else {
                nowMap = (Map) obj;
            }
        }
        nowMap.put("isEnd", "true");
    }

    /**
     * 读取敏感词文件
     *
     * @return
     */
    private static Set<String> readSensitiveWords() {
        Set<String> keyWords = new HashSet<>();
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new InputStreamReader(in, ENCODING));
            String line;
            while ((line = reader.readLine()) != null) {
                keyWords.add(line.trim());
            }
        } catch (UnsupportedEncodingException e) {
            LOG.error("敏感词库文件转码失败!");
        } catch (FileNotFoundException e) {
            LOG.error("敏感词库文件不存在!");
        } catch (IOException e) {
            LOG.error("敏感词库文件读取失败!");
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                reader = null;
            }
        }
        return keyWords;
    }

    /**
     * 检查敏感词
     *
     * @return
     */
    private static List<String> checkSensitiveWord(String text) {
        if (sensitiveWordMap == null) {
            init();
        }
        List<String> sensitiveWords = new ArrayList<>();
        Map nowMap = sensitiveWordMap;
        for (int i = 0; i < text.length(); i++) {
            Character word = text.charAt(i);
            Object obj = nowMap.get(word);
            if (obj == null) {
                continue;
            }
            int j = i + 1;
            Map childMap = (Map) obj;
            while (j < text.length()) {
                if ("true".equals(childMap.get("isEnd"))) {
                    sensitiveWords.add(text.substring(i, j));
                }
                obj = childMap.get(text.charAt(j));
                if (obj != null) {
                    childMap = (Map) obj;
                } else {
                    break;
                }
                j++;
            }
        }
        return sensitiveWords;
    }
}

2.TTMP算法

TTMP算法由网友原创,关于它的起源可以查看这里,TTMP算法的原理是将敏感词拆分成“脏字”的序列,只有待比对字符串完全由“脏字”组成时,才去判断它是否为敏感词,减少了比对次数。这个算法的简单实现如下:

public class TextFilterUtil {

    //日志
    private static final Logger LOG = LoggerFactory.getLogger(TextFilterUtil.class);
    //默认编码格式
    private static final String ENCODING = "gbk";
    //敏感词库的路径
    private static final InputStream in = TextFilterUtil.class.getClassLoader().getResourceAsStream("sensitive/keyWords.txt");
    //脏字库
    private static Set<Character> sensitiveCharSet = null;
    //敏感词库
    private static Set<String> sensitiveWordSet = null;

    /**
     * 初始化敏感词库
     */
    private static void init() {
        //初始化容器
        sensitiveCharSet = new HashSet<>();
        sensitiveWordSet = new HashSet<>();
        //读取文件 创建敏感词库
        readSensitiveWords();
    }

    /**
     * 读取本地的敏感词文件
     *
     * @return
     */
    private static void readSensitiveWords() {
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new InputStreamReader(in, ENCODING));
            String line;
            while ((line = reader.readLine()) != null) {
                String word = line.trim();
                sensitiveWordSet.add(word);
                for (Character c : word.toCharArray()) {
                    sensitiveCharSet.add(c);
                }
            }
        } catch (UnsupportedEncodingException e) {
            LOG.error("敏感词库文件转码失败!");
        } catch (FileNotFoundException e) {
            LOG.error("敏感词库文件不存在!");
        } catch (IOException e) {
            LOG.error("敏感词库文件读取失败!");
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                reader = null;
            }
        }
        return;
    }

    /**
     * 检查敏感词
     *
     * @return
     */
    private static List<String> checkSensitiveWord(String text) {
        if (sensitiveWordSet == null || sensitiveCharSet == null) {
            init();
        }
        List<String> sensitiveWords = new ArrayList<>();
        for (int i = 0; i < text.length(); i++) {
            Character word = text.charAt(i);
            if (!sensitiveCharSet.contains(word)) {
                continue;
            }
            int j = i;
            while (j < text.length()) {
                if (!sensitiveCharSet.contains(word)) {
                    break;
                }
                String key = text.substring(i, j + 1);
                if (sensitiveWordSet.contains(key)) {
                    sensitiveWords.add(key);
                }
                j++;
            }
        }
        return sensitiveWords;
    }
}

注:以上代码实现仅用于展示思路,在实际使用中还有很多地方可以优化。

时间: 2024-10-08 04:11:58

[Java Web]敏感词过滤算法的相关文章

转:Java实现敏感词过滤

敏感词.文字过滤是一个网站必不可少的功能,如何设计一个好的.高效的过滤算法是非常有必要的.前段时间我一个朋友(马上毕业,接触编程不久)要我帮他看一个文字过滤的东西,它说检索效率非常慢.我把它程序拿过来一看,整个过程如下:读取敏感词库.如果HashSet集合中,获取页面上传文字,然后进行匹配.我就想这个过程肯定是非常慢的.对于他这个没有接触的人来说我想也只能想到这个,更高级点就是正则表达式.但是非常遗憾,这两种方法都是不可行的.当然,在我意识里没有我也没有认知到那个算法可以解决问题,但是Googl

Java实现敏感词过滤

敏感词.文字过滤是一个网站必不可少的功能,如何设计一个好的.高效的过滤算法是非常有必要的.前段时间我一个朋友(马上毕业,接触编程不久)要我帮他看一个文字过滤的东西,它说检索效率非常慢.我把它程序拿过来一看,整个过程如下:读取敏感词库.如果HashSet集合中,获取页面上传文字,然后进行匹配.我就想这个过程肯定是非常慢的.对于他这个没有接触的人来说我想也只能想到这个,更高级点就是正则表达式.但是非常遗憾,这两种方法都是不可行的.当然,在我意识里没有我也没有认知到那个算法可以解决问题,但是Googl

Java实现敏感词过滤(转)

敏感词.文字过滤是一个网站必不可少的功能,如何设计一个好的.高效的过滤算法是非常有必要的.前段时间我一个朋友(马上毕业,接触编程不久)要我帮他看一个文字过滤的东西,它说检索效率非常慢.我把它程序拿过来一看,整个过程如下:读取敏感词库.如果HashSet集合中,获取页面上传文字,然后进行匹配.我就想这个过程肯定是非常慢的.对于他这个没有接触的人来说我想也只能想到这个,更高级点就是正则表达式.但是非常遗憾,这两种方法都是不可行的.当然,在我意识里没有我也没有认知到那个算法可以解决问题,但是Googl

浅析敏感词过滤算法(C++)

为了提高查找效率,这里将敏感词用树形结构存储,每个节点有一个map成员,其映射关系为一个string对应一个TreeNode. STL::map是按照operator<比较判断元素是否相同,以及比较元素的大小,然后选择合适的位置插入到树中.为了提高map的插入及查询效率,可以选用hash_map或unordered_map.关于他们的效率,可以参考http://blog.csdn.net/whizchen/article/details/9286557. 下面主要实现了TreeNode类,进行节

java实现敏感词过滤(DFA算法)

小Alan在最近的开发中遇到了敏感词过滤,便去网上查阅了很多敏感词过滤的资料,在这里也和大家分享一下自己的理解. 在写之前,小Alan给大家推荐一篇来自http://cmsblogs.com/?p=1031的博文,也会参考部分内容来描述博文. 敏感词过滤应该是不用给大家过多的解释吧?讲白了就是你在项目中输入某些字(比如输入xxoo相关的文字时)时要能检测出来,很多项目中都会有一个敏感词管理模块,在敏感词管理模块中你可以加入敏感词,然后根据加入的敏感词去过滤输入内容中的敏感词并进行相应的处理,要么

敏感词过滤算法:前缀树算法

背景 平时我们在逛贴吧的时候,我们经常可以看到一些形如 “***”的符号,通过上下文,我们也可以很容易猜到这些词原来是骂人的话,只是被系统和谐了.那么这是如何实现的呢?作为普通人,我们最先想到的一种办法就是把所有敏感串存入一个列表中,然后用户每发一条内容后台就把该内容与敏感串列表的每一项进行匹配,然后把匹配的字符进行和谐.显然这样的效率是很低的.非常影响性能,那么我们有没有其他的算法呢?这就是我这篇博文打算介绍的. 原理讲解 1.首先建立个敏感词前缀树 根节点为空 2.准备好待处理字符串: 哈哈

敏感词过滤的算法原理之DFA算法

参考文档 http://blog.csdn.net/chenssy/article/details/26961957 敏感词.文字过滤是一个网站必不可少的功能,如何设计一个好的.高效的过滤算法是非常有必要的.前段时间我一个朋友(马上毕业,接触编程不久)要我帮他看一个文字过滤的东西,它说检索效率非常慢.我把它程序拿过来一看,整个过程如下:读取敏感词库.如果HashSet集合中,获取页面上传文字,然后进行匹配.我就想这个过程肯定是非常慢的.对于他这个没有接触的人来说我想也只能想到这个,更高级点就是正

敏感词过滤

敏感词过滤是很多网站.论坛常用的功能,一下为相关文章: 1.关于java中敏感词检测的一些总结 2.Java 利用DFA算法 屏蔽敏感词 3.Java实现敏感词过滤--DFA算法

java敏感词过滤

敏感词过滤在网站开发必不可少.一般用DFA,这种比较好的算法实现的. 参考链接:http://cmsblogs.com/?p=1031 一个比较好的代码实现: 1 import java.io.IOException; 2 import java.util.ArrayList; 3 import java.util.HashMap; 4 import java.util.List; 5 6 /** 7 * @title KeywordFilter 8 * @description TODO 9