[Java Web]敏感词过滤算法

标签: java web 敏感词 | 发表时间:2015-01-19 21:26 | 作者:sinat_19425927
出处:http://blog.csdn.net

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;
    }
}

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




作者:sinat_19425927 发表于2015-1-19 13:26:21 原文链接
阅读:0 评论:0 查看评论

相关 [java web 敏感词] 推荐:

[Java Web]敏感词过滤算法

- - CSDN博客推荐文章
DFA算法的原理可以参考 这里,简单来说就是通过Map构造出一颗敏感词树,树的每一条由根节点到叶子节点的路径构成一个敏感词,例如下图:. LOG.error("sensitiveWordMap 未初始化!");. LOG.error("敏感词库文件转码失败!");. LOG.error("敏感词库文件不存在!");.

xssProject在java web项目中应用

- - Java - 编程语言 - ITeye博客
1.项目引入xssProtect-0.1.jar、antlr-3.0.1.jar、antlr-runtime-3.0.1.jar包. * 覆盖getParameter方法,将参数名和参数值都做xss过滤. * 如果需要获得原始的值,则通过super.getParameterValues(name)来获取
.

java web开发 高并发处理

- - 企业架构 - ITeye博客
java web开发 高并发处理. java处理高并发高负载类网站中数据库的设计方法(java教程,java处理大量数据,java高负载数据). 一:高并发高负载类网站关注点之数据库. 没错,首先是数据库,这是大多数应用所面临的首个SPOF. 尤其是Web2.0的应用,数据库的响应是首先要解决的. 一般来说MySQL是最常用的,可能最初是一个mysql主机,当数据增加到100万以上,那么,MySQL的效能急剧下降.

关于Java Web打印的选择

- - JavaScript - Web前端 - ITeye博客
 最近遇到一个项目,需要用到较为复杂的打印功能,包括批量打印等. 目前来说,一般一个简单的详情页面打印,直接调用window.print就行了;. 但遇到复杂的时候,我们可能会想到用集成好的控件来解决,当然,如果你有时间又不怕麻烦,你也可以自己写一堆js. 这里,我就先抛砖引玉对两个比较常用的打印控件谈谈自己的看法.

Java Web 服务性能优化实践

- - 博客 - 伯乐在线
来源: IBM developerworks. 简介: 本文介绍如何提升 Java Web 服务性能,主要介绍了三种方法:一是采用 Web 服务的异步调用,二是引入 Web 服务批处理模式,三是压缩 SOAP 消息. 重点介绍在编程过程中如何使用异步 Web 服务以及异步调用和同步调用的差异点. 本文还示范了如何在项目中使用以上三种方法,以及各种方法所适合的应用场景.

使用Gradle构建Java Web应用(译)

- - BlogJava-首页技术区
使用Gradle构建Java Web应用. 本文是发布在 java.net上的一篇摘自于一书中的 节选,介绍了使用 Gradle构建Java Web应用的过程. 刚刚接触Gradle,看到了这篇小文,随手译了出来:-) (2014.01.23最后更新). 在职业生涯和私人生活中,我们中间的许多人要同时管理多个项目.

Java Web应用Web层异步化应该考虑的问题

- - 企业架构 - ITeye博客
        之前做了一个项目,要用到web层的异步化技术,在实际实现中,遇到了很多问题,作为教训简单罗列下. 1、app 容器/J2EE框架对异步的支持.         在tomcat5、jboss4的时候,每一个请求都用了一个app容器线程来执行,app线程必须一直处理完或者等待别的线程处理完,才能拿着请求的链接把结果写回到客户端.

Java 开发 2.0: 使用 Gretty 的超轻量级 Java Web 服务

- 圣斌 - IBM developerWorks 中国 : 文档库
Gretty 是构建 Web 服务超轻量级框架的新学派之一. 构建于极快的 Java NIO API 之上,Gretty 将 Groovy 用作 Web 端点和 Grape 的 Maven 式依赖关系管理的一种域特定语言. 本文介绍如何开始使用 Gretty 来构建和部署 Java Web 服务应用程序.

构建实时Web的JAVA选择组合:socket.io client + socketio-netty server

- - BlogJava-首页技术区
     摘要: 很显然,实时Web,是一种技术趋势,将成为一种人们的默认技术选择,用以拉近和桌面应用的距离. socket.io是一种数据实时推送、事件驱动模型的框架,支持事件订阅,简单易用. 其价值目前看来,还未被完整的挖掘出来. socket.io即提供了node.js服务器端(地址)又提供了客户端(地址)的整体解决方案,而socketio-netty则是基于JAVA服务器端,支持最新socket.io client最新版规范.

java实现web文件无刷新上传

- - CSDN博客推荐文章
最近在做如何实现文件上传的相关工作,查阅了很多资料,发现网上写的都不是很直观,且调试复杂,经实验成功. 把form的target设为页面里一个看不见的iframe,这样上传时候就不会刷新页面了,比如 :. .