过滤敏感词方式

一、利用正则表达式

关键正则表达式

.*(关键词1|关键词2|关键词3).*

模拟业务代码

@WebServlet(name = "PatternControl", urlPatterns = {"/p"})
public class PatternControl extends HttpServlet {
    private static final Pattern pattern = initPattern();

    private static Pattern initPattern() {
        List<String> stringList = null;
        try {
            stringList = Files.readAllLines(Paths.get("/Users/hans/Documents/word.txt"));
        } catch (IOException e) {
            e.printStackTrace();
        }
        StringBuilder stringBuilder = new StringBuilder(".*(");
        stringBuilder.append(stringList.get(0));
        for (int i = 1; i < stringList.size(); i++) {
            stringBuilder.append("|" + stringList.get(i));
        }
        stringBuilder.append(").*");
        Pattern pattern = Pattern.compile(stringBuilder.toString());
        return pattern;
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        if (pattern == null) {
            response.sendError(500, "pattern is null");
            return;
        }
        if (request.getParameter("word") == null) {
            response.sendError(500, "word is null");
            return;
        }
        boolean isMatcher = pattern.matcher(request.getParameter("word")).matches();
        if (isMatcher) {
            response.sendError(209);
        } else {
            response.sendError(409);
        }
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }
}

时间空间占用情况

前提

关键词共有28448个,将其编译成上述的正则表达式

CPU 2.2GHz Intel i7四核
内存
16GB 1600 MHz DDR3

时间情况(多次实验平均结果)

阶段 耗时(ms)
初始化
读取敏感词:38

编译正则表达式:41

每次匹配 47

空间情况(多次实验平均结果)

阶段 消耗内存(MB)
初始化 编译正则表达式 11
每次匹配 极小

cpu和堆运行时情况图

结论

利用正则表达式过滤敏感词效果较好

二、利用字符串暴力匹配

核心思路

循环总共关键词个数次,判断时候在待匹配字符串中 是否包含 本次循环的关键词

模拟业务代码

@WebServlet(name = "PatternControl", urlPatterns = {"/p"})
public class PatternControl extends HttpServlet {
    private static final List<String> stringList = initStringList();

    private static List<String> initStringList() {
        List<String> stringList = null;
        try {
            stringList = Files.readAllLines(Paths.get("/Users/hans/Documents/word.txt"));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return stringList;
    }

    private boolean matchKeyWord(String text) {
        for (String markWord : stringList) {
            if (text.contains(markWord)) {
                return true;
            }
        }
        return false;
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        if (request.getParameter("word") == null) {
            response.sendError(500, "word is null");
            return;
        }
        boolean isMatcher = matchKeyWord(request.getParameter("word"));
        if (isMatcher) {
            response.sendError(209);
        } else {
            response.sendError(409);
        }
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }
}

时间空间占用情况

时间情况(多次实验平均结果)

阶段 耗时(ms)
初始化
读取敏感词:38

每次匹配 10

空间情况(多次实验平均结果)

阶段 消耗内存(MB)
初始化 3
每次匹配 极小

结论

利用暴力匹配的效果更好

三、利用Tire树匹配

核心思路

将所有的敏感词构成一棵路径树,每个节点只有一个字符

模拟业务代码

public class TestAcWithoutFail {
    public void insert(String str, Node root) {
        Node p = root;
        for (char c : str.toCharArray()) {
            if (p.childrenNodes.get(c) == null) {
                p.childrenNodes.put(c, new Node());
            }
            p = p.childrenNodes.get(c);
        }
        p.isEnd = true;
    }

    public boolean isContainSensitiveWord(String text, Node root) {
        for (int i = 0; i < text.length(); i++) {
            Node nowNode = root;
            for (int j = i; j < text.length(); j++) {
                char word = text.charAt(j);
                nowNode = nowNode.childrenNodes.get(word);
                if (nowNode != null) {
                    if (nowNode.isEnd) {
                        return true;
                    }
                } else {
                    break;
                }
            }
        }
        return false;
    }
    public String containSensitiveWord(String text, Node root) {
    		for (int i = 0; i < text.length(); i++) {
        		Node nowNode = root;
        		for (int j = i; j < text.length(); j++) {
            		char word = text.charAt(j);
            		nowNode = nowNode.childrenNodes.get(word);
            		if (nowNode != null) {
                		if (nowNode.isEnd) {
                    	return text.substring(i, j + 1);
                		}
            		} else {
                		break;
           		}
        	}
    	}
    	return "";
	}

    public static void main(String[] args) throws IOException, InterruptedException {
        List<String> stringList = Files.readAllLines(Paths.get("/Users/hans/Documents/word.txt"));
        TestAcWithoutFail acNoFail = new TestAcWithoutFail();
        Node root = new Node();
        for (String text : stringList) {
            acNoFail.insert(text, root);
        }
        String string = "tiresdfsdffffffffffaaaaaaaaaa";
        Thread.sleep(10 * 1000);
        for (int i = 0; i < 1; i++) {
            System.out.println(acNoFail.isContainSensitiveWord(string, root));
        }
    }
}

class Node {
    Map<Character, Node> childrenNodes = new HashMap<>();
    boolean isEnd;
}

时间空间占用情况

时间情况(多次实验平均结果)

阶段 耗时(ms)
初始化
读取敏感词:38

构建比较树:36

每次匹配 0.01量级(执行1000遍34ms、执行10000遍130ms) 

空间情况(多次实验平均结果)

阶段 消耗内存(MB)
初始化
读取字符串:3

构建比较树:24

每次匹配 极小

结论

在该业务中和暴力匹配效果哪个好值得商榷

四、服务部署方式

主站的做法(刘乐那边的做法一样)

  • 单独部署一台服务器
  • 将关键词放到一张表中
  • 设置定时任务每天初始化一次

我的方案

  • 将关键词放到一张表中
  • 设置定时任务每天初始化一次(其实感觉每天更新都挺浪费的,写个接口,表中数据改了之后,调用一下就可以)
  • 多台机器上每个机器都每天读取一次数据库,解决同步的问题(或者用Tair缓存这些数据,但我感觉是不是弄麻烦了)
时间: 2024-10-29 16:28:24

过滤敏感词方式的相关文章

DFA算法过滤敏感词整理

这里有部分是从网上找的,但看起来太乱了,分的太散了.研究了几天,整理出来,有问题的话还请大虾们提出来.... package org.rui.util; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.util.HashMap; i

[转]Filter实现处理中文乱码,转义html标签,过滤敏感词

原文地址:http://www.cnblogs.com/xdp-gacl/p/3952405.html 在filter中可以得到代表用户请求和响应的request.response对象,因此在编程中可以使用Decorator(装饰器)模式对request.response对象进行包装,再把包装对象传给目标资源,从而实现一些特殊需求. 一.Decorator设计模式 1.1.Decorator设计模式介绍 当某个对象的方法不适应业务需求时,通常有2种方式可以对方法进行增强: 编写子类,覆盖需增强的

javaEE之---------过滤敏感词(filter)

我们在聊天的时候的或者留言的时候,有部分词是不允许发表出来.我们可以采用过滤器实现这个功能. 我们只是简单利用过滤器实现这个过滤的功能,有些地方没写的很全 前台代码: <span style="font-size:18px;"> <body> <form action="<c:url value='/WordServlet'/>" method="post"> 姓名:<input type=&

js 过滤敏感词 ,可将带有标点符号的敏感词过滤掉

function transSensitive(content) { // var Sensitive = H.getStorage("Sensitive");//敏感词数组 var Sensitive=["张三","李四"];//敏感词数组 var v = new RegExp(Sensitive.join('|'), "gi");//将数组转成正则 var array = new Array(); //将特殊符号的过滤并且

php过滤敏感词

<?php /**  * 敏感词过滤工具类  * 使用方法  * echo FilterTools::filterContent("你妈的我操一色狼杂种二山食物","*",DIR."config/word.txt",$GLOBALS["p_memcache"]["bad_words"]);  */ class FilterTools {     public static $keyword = arr

text1 正则过滤敏感词。

直播平台,内容,聊天网站对用户输入的敏感词进行屏蔽. 例如,写两个文本域和一个btn按钮.当按钮按下时.将用户输入的敏感词转化为"**",再把文本变成转化后的文本. 例子如下: btn.onclick=function(){ var re=/忠臣|反贼|内奸/g: oText2.value=oTxt1.value.replace(re,"**"); }

20170513 Python练习册0011过滤敏感词

#!/usr/bin/env python# -*-coding:utf-8-*- # 第 0011 题: 敏感词文本文件 filtered_words.txt,里面的内容为以下内容,# 当用户输入敏感词语时,则打印出 Freedom,否则打印出 Human Rights.import re def filted_word(filename): word_list=[]#定义一个空列表 with open(filename,'r') as f:#以读打开文件 for line in f:#以行为

多线程过滤敏感词

原文:https://git.oschina.net/tianzhenjiu/codes/y9z6t471s3euinoj5vcdf79 package io.test; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Ex

Python爬虫框架Scrapy 学习笔记 5 ------- 使用pipelines过滤敏感词

还是上一篇博客的那个网站,我们增加了pipeline.py items.py from scrapy.item import Item, Field class Website(Item):     name = Field()     description = Field()     url = Field() dmoz.py from scrapy.spider import Spider from scrapy.selector import Selector from dirbot.i