mysql 敏感词_过滤敏感词方式
一、利用正則表達式
關鍵正則表達式
.*(關鍵詞1|關鍵詞2|關鍵詞3).*
模擬業務代碼
@WebServlet(name = "PatternControl", urlPatterns = {"/p"})
public class PatternControl extends HttpServlet {
private static final Pattern pattern = initPattern();
private static Pattern initPattern() {
List 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個,將其編譯成上述的正則表達式
CPU2.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 stringList = initStringList();
private static List initStringList() {
List 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 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 childrenNodes = new HashMap<>();
boolean isEnd;
}
時間空間占用情況
時間情況(多次實驗平均結果)
階段耗時(ms)
初始化
讀取敏感詞:38
構建比較樹:36
每次匹配
0.01量級(執行1000遍34ms、執行10000遍130ms)
空間情況(多次實驗平均結果)
階段消耗內存(MB)
初始化
讀取字符串:3
構建比較樹:24
每次匹配
極小
結論
在該業務中和暴力匹配效果哪個好值得商榷
四、服務部署方式
主站的做法(劉樂那邊的做法一樣)
單獨部署一臺服務器
將關鍵詞放到一張表中
設置定時任務每天初始化一次
我的方案
將關鍵詞放到一張表中
設置定時任務每天初始化一次(其實感覺每天更新都挺浪費的,寫個接口,表中數據改了之后,調用一下就可以)
多臺機器上每個機器都每天讀取一次數據庫,解決同步的問題(或者用Tair緩存這些數據,但我感覺是不是弄麻煩了)
總結
以上是生活随笔為你收集整理的mysql 敏感词_过滤敏感词方式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 镜头选型
- 下一篇: 关于cmake从GitHub上下载的源码