本文資源來自:https://github.com/k5h9999/keywordfilter
作者: k5h9999
說明:基于分詞原理修改寫的一個過濾敏感詞庫忆家,可以改成動態(tài)闻蛀,本敏感詞收集了4W多個違法詞押搪、敏感詞港华、違禁詞鱼冀,幾十個矯正詞累铅、變異詞糕非。
最近做Android項目用到敏感詞校驗功能蒙具,原本想到用在線檢測功能,不過太依賴于網(wǎng)絡(luò)朽肥,而且校驗服務(wù)器也不一定能一直開通禁筏,于是想到了找一下離線庫。
文章開頭的鏈接是作者為Java寫的代碼衡招,我稍加修改篱昔,將其用到了我的Android項目中。感謝原作者的分享蚁吝。
下面是步驟:
1.將詞庫放到項目中
將上述項目文件src\main\resources\META-INF\dic
目錄中的兩個文件:fqc.dic
和wfc.dic
解壓縮旱爆,放到Android項目的assets
資源文件夾中。如果Android項目中沒有這個文件夾窘茁,在main
目錄下自己新建即可怀伦。
2.修改代碼適配Android
作者的原項目中只有兩個類,WordFilter
和KeyWordFilter
山林,其中在WordFilter
類中持有對KeyWordFilter
的引用房待。
我們打開KeyWordFilter
邢羔,找到main
方法,查看用法桑孩,發(fā)現(xiàn)里面有這樣的代碼:
public static void main(String[] args) {
String str = "一個網(wǎng)站就像一個人拜鹤,存在一個從小到大白粉的過程。養(yǎng)一個網(wǎng)站和養(yǎng)一個人一樣流椒,不同時期漂白粉需要不同的方法敏簿,口交--不同的方法下有共24口交換機同的原則。";
Long startTime = System.currentTimeMillis();
WordFilter wf = new WordFilter();
//WordFilter.filter_search(String) 方法是從字符串中刪除敏感詞后返回結(jié)果
System.out.println(wf.filter_search(str));
//WordFilter.filter_jk_info(String)方法是將敏感詞標(biāo)記出來
System.out.println(wf.filter_jk_info("一個網(wǎng)站就像一個人"));
Long endTime = System.currentTimeMillis();
System.out.println("時間:" + (endTime - startTime));
}
我們找到filter_jk_info
方法宣虾,查看其實現(xiàn):
public String filter_jk_info(String content){
return kwf.filter_jk(content,"0","0","<font color=#ff0000>","</font>","<font color=#00ff00>","</font>");
}
再轉(zhuǎn)到filter_jk
方法惯裕,發(fā)現(xiàn)這里就是核心算法。對比結(jié)果發(fā)現(xiàn)绣硝,此方法是將敏感詞用html標(biāo)簽標(biāo)記為紅色和綠色蜻势。
我們直接嘗試調(diào)用會報空指針
異常。跟隨異常信息鹉胖,發(fā)現(xiàn)原來是讀取詞庫的時候握玛,數(shù)據(jù)流報空指針錯誤:
KeyWordFilter.java
private HashMap<String, String> getWordMap(String dicPath, String replace) {
InputStream is = null;
HashMap<String, String> wordMap = new HashMap<String, String>();
try {
//就是下面這一行返回的is為空
is = KeyWordFilter.class.getResourceAsStream(dicPath);
if (is == null) {
System.out.println(dicPath + " not found!!!");
}
BufferedReader br = new BufferedReader(new InputStreamReader(is,
"UTF-8"), 512);
String theWord = null;
//
// 省略部分代碼
//
}
首先將詞庫文件的全局變量路徑修改為:
public static final String PATH_DIC_WFC = "wfc.dic";
public static final String PATH_DIC_FQC = "fqc.dic";
然后將空指針那一行代碼改成:
is = App.getContext().getResources().getAssets().open(dicPath);
其中App.getContext()
是自定義Application
中的方法,自己添加即可甫菠。
這樣就獲取到了assets
目錄下的文件挠铲,并返回了InputStream
。
最后寂诱,就可以調(diào)用了市殷。
WordFilter mKeywordFilter = new WordFilter();
String s = mKeywordFilter.filter_jk_info2(content);
filter_jk_info2
方法的返回值為:
- 如果沒有敏感詞,返回原文刹衫;
- 如果有敏感詞,返回將敏感詞標(biāo)記后的字符串搞挣,標(biāo)記規(guī)則在
KeyWordFilter.filter_jk
方法中带迟。
所以,我們可以修改filter_jk_info
方法如下:
public String filter_jk_info(String content) {
return kwf.filter_jk(content, "0", "0", "<mgc>", "</mgc>", "<mgc>", "</mgc>");
}
然后判斷返回值s
是否包含<mgc>
標(biāo)簽即可囱桨。
總結(jié)修改
WordFilter.java
public String filter_jk_info2(String content) {
return kwf.filter_jk(content, "0", "0", "<mgc>", "</mgc>", "<mgc>", "</mgc>");
}
KeyWordFilter.java
public static final String PATH_DIC_WFC = "wfc.dic";
public static final String PATH_DIC_FQC = "fqc.dic";
private HashMap<String, String> getWordMap(String dicPath, String replace) {
InputStream is = null;
HashMap<String, String> wordMap = new HashMap<String, String>();
try {
is = App.getContext().getResources().getAssets().open(dicPath);
if (is == null) {
System.out.println(dicPath + " not found!!!");
}
BufferedReader br = new BufferedReader(new InputStreamReader(is,
"UTF-8"), 512);
String theWord = null;
//
// 省略部分代碼
//
}
使用:
private WordFilter mKeywordFilter;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
// 省略部分代碼
mKeywordFilter = new WordFilter();
//因為內(nèi)部是靜態(tài)對象仓犬,所以這里先調(diào)用一次生成實例,后面可以加速查找過程舍肠,懶得改源碼了
new Thread(() -> mKeywordFilter.filter_jk_info2("初始化")).start();
}
public void checkContent(){
String s = mKeywordFilter.filter_jk_info("測試內(nèi)容");
if(s.contains("<mgc>") || s.contains("</mgc>")){
//包含敏感詞的操作
}
}