程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> java利用DFA算法實現敏感詞過濾功能

java利用DFA算法實現敏感詞過濾功能

編輯:關於JAVA

前言

敏感詞過濾應該是不用給大家過多的解釋吧?講白了就是你在項目中輸入某些字(比如輸入xxoo相關的文字時)時要能檢

測出來,很多項目中都會有一個敏感詞管理模塊,在敏感詞管理模塊中你可以加入敏感詞,然後根據加入的敏感詞去過濾輸

入內容中的敏感詞並進行相應的處理,要麼提示,要麼高亮顯示,要麼直接替換成其它的文字或者符號代替。

敏感詞過濾的做法有很多,我簡單描述我現在理解的幾種:

①查詢數據庫當中的敏感詞,循環每一個敏感詞,然後去輸入的文本中從頭到尾搜索一遍,看是否存在此敏感詞,有則做相

應的處理,這種方式講白了就是找到一個處理一個。

優點:so easy。用java代碼實現基本沒什麼難度。

缺點:這效率讓我心中奔過十萬匹草泥馬,而且匹配的是不是有些蛋疼,如果是英文時你會發現一個很無語的事情,比如英文

a是敏感詞,那我如果是一篇英文文檔,那程序它妹的得處理多少次敏感詞?誰能告訴我?

②傳說中的DFA算法(有窮自動機),也正是我要給大家分享的,畢竟感覺比較通用,算法的原理希望大家能夠自己去網上查查

資料,這裡就不詳細說明了。

優點:至少比上面那sb效率高點。

缺點:對於學過算法的應該不難,對於沒學過算法的用起來也不難,就是理解起來有點gg疼,匹配效率也不高,比較耗費內存,

敏感詞越多,內存占用的就越大。

③第三種在這裡要特別說明一下,那就是你自己去寫一個算法吧,或者在現有的算法的基礎上去優化,這也是追求的至高境界之一。

那麼,傳說中的DFA算法是怎麼實現的呢?

第一步:敏感詞庫初始化(將敏感詞用DFA算法的原理封裝到敏感詞庫中,敏感詞庫采用HashMap保存),代碼如下:

package com.cfwx.rox.web.sysmgr.util;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.cfwx.rox.web.common.model.entity.SensitiveWord;

/**
 * 敏感詞庫初始化
 * 
 * @author AlanLee
 *
 */
public class SensitiveWordInit
{
  /**
   * 敏感詞庫
   */
  public HashMap sensitiveWordMap;

  /**
   * 初始化敏感詞
   * 
   * @return
   */
  public Map initKeyWord(List<SensitiveWord> sensitiveWords)
  {
    try
    {
      // 從敏感詞集合對象中取出敏感詞並封裝到Set集合中
      Set<String> keyWordSet = new HashSet<String>();
      for (SensitiveWord s : sensitiveWords)
      {
        keyWordSet.add(s.getContent().trim());
      }
      // 將敏感詞庫加入到HashMap中
      addSensitiveWordToHashMap(keyWordSet);
    }
    catch (Exception e)
    {
      e.printStackTrace();
    }
    return sensitiveWordMap;
  }

  /**
   * 封裝敏感詞庫
   * 
   * @param keyWordSet
   */
  @SuppressWarnings("rawtypes")
  private 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);
    }
  }
}

第二步:寫一個敏感詞過濾工具類,裡面可以寫上自己需要的方法,代碼如下:

package com.cfwx.rox.web.sysmgr.util;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * 敏感詞過濾工具類
 * 
 * @author AlanLee
 *
 */
public class SensitivewordEngine
{
  /**
   * 敏感詞庫
   */
  public static Map sensitiveWordMap = null;

  /**
   * 只過濾最小敏感詞
   */
  public static int minMatchTYpe = 1;

  /**
   * 過濾所有敏感詞
   */
  public static int maxMatchType = 2;

  /**
   * 敏感詞庫敏感詞數量
   * 
   * @return
   */
  public static int getWordSize()
  {
    if (SensitivewordEngine.sensitiveWordMap == null)
    {
      return 0;
    }
    return SensitivewordEngine.sensitiveWordMap.size();
  }

  /**
   * 是否包含敏感詞
   * 
   * @param txt
   * @param matchType
   * @return
   */
  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)
      {
        flag = true;
      }
    }
    return flag;
  }

  /**
   * 獲取敏感詞內容
   * 
   * @param txt
   * @param matchType
   * @return 敏感詞內容
   */
  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;
  }

  /**
   * 替換敏感詞
   * 
   * @param txt
   * @param matchType
   * @param replaceChar
   * @return
   */
  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;
  }

  /**
   * 替換敏感詞內容
   * 
   * @param replaceChar
   * @param length
   * @return
   */
  private static String getReplaceChars(String replaceChar, int length)
  {
    String resultReplace = replaceChar;
    for (int i = 1; i < length; i++)
    {
      resultReplace += replaceChar;
    }

    return resultReplace;
  }

  /**
   * 檢查敏感詞數量
   * 
   * @param txt
   * @param beginIndex
   * @param matchType
   * @return
   */
  public static int checkSensitiveWord(String txt, int beginIndex, int matchType)
  {
    boolean flag = false;
    // 記錄敏感詞數量
    int matchFlag = 0;
    char word = 0;
    Map nowMap = SensitivewordEngine.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 (SensitivewordEngine.minMatchTYpe == matchType)
          {
            break;
          }
        }
      }
      else
      {
        break;
      }
    }
    if (!flag)
    {
      matchFlag = 0;
    }
    return matchFlag;
  }

}

第三步:一切都准備就緒,當然是查詢好數據庫當中的敏感詞,並且開始過濾咯,代碼如下:

@SuppressWarnings("rawtypes")
  @Override
  public Set<String> sensitiveWordFiltering(String text)
  {
    // 初始化敏感詞庫對象
    SensitiveWordInit sensitiveWordInit = new SensitiveWordInit();
    // 從數據庫中獲取敏感詞對象集合(調用的方法來自Dao層,此方法是service層的實現類)
    List<SensitiveWord> sensitiveWords = sensitiveWordDao.getSensitiveWordListAll();
    // 構建敏感詞庫
    Map sensitiveWordMap = sensitiveWordInit.initKeyWord(sensitiveWords);
    // 傳入SensitivewordEngine類中的敏感詞庫
    SensitivewordEngine.sensitiveWordMap = sensitiveWordMap;
    // 得到敏感詞有哪些,傳入2表示獲取所有敏感詞
    Set<String> set = SensitivewordEngine.getSensitiveWord(text, 2);
    return set;
  }

最後一步:在Controller層寫一個方法給前端請求,前端獲取到需要的數據並進行相應的處理,代碼如下:

/**
   * 敏感詞過濾
   * 
   * @param text
   * @return
   */
  @RequestMapping(value = "/word/filter")
  @ResponseBody
  public RespVo sensitiveWordFiltering(String text)
  {
    RespVo respVo = new RespVo();
    try
    {
      Set<String> set = sensitiveWordService.sensitiveWordFiltering(text);
      respVo.setResult(set);
    }
    catch (Exception e)
    {
      throw new RoxException("過濾敏感詞出錯,請聯系維護人員");
    }

    return respVo;
  }

總結

以上就是這篇文章的全部內容了,代碼中寫了不少的注釋,大家可以動動自己的腦筋好好的理解一下。希望本文的內容對大家的學習或者工作能帶來一定的幫助,如果有疑問大家可以留言交流,謝謝大家對的支持。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved