js實(shí)現(xiàn)敏感詞過(guò)濾算法及實(shí)現(xiàn)邏輯
最近弄了一個(gè)用戶(hù)發(fā)表評(píng)論的功能,用戶(hù)上傳了評(píng)論,再文章下可以看到自己的評(píng)論,但作為社會(huì)主義接班人,踐行社會(huì)主義核心價(jià)值觀,所以給評(píng)論敏感詞過(guò)濾的功能不可少,在網(wǎng)上找了資料,發(fā)現(xiàn)已經(jīng)有非常成熟的解決方案。 常用的方案用這么兩種
1.全文搜索,逐個(gè)匹配。這種聽(tīng)起來(lái)就不夠高大上,在數(shù)據(jù)量大的情況下,會(huì)有效率問(wèn)題,文末有比較
2.DFA算法-確定有限狀態(tài)自動(dòng)機(jī) 附上百科鏈接確定有限狀態(tài)自動(dòng)機(jī)
DFA算法介紹
DFA是一種計(jì)算模型,數(shù)據(jù)源是一個(gè)有限個(gè)集合,通過(guò)當(dāng)前狀態(tài)和事件來(lái)確定下一個(gè)狀態(tài),即 狀態(tài)+事件=下一狀態(tài),由此逐步構(gòu)建一個(gè)有向圖,其中的節(jié)點(diǎn)就是狀態(tài),所以在DFA算法中只有查找和判斷,沒(méi)有復(fù)雜的計(jì)算,從而提高算法效率
參考文章 Java實(shí)現(xiàn)敏感詞過(guò)濾
實(shí)現(xiàn)邏輯
構(gòu)造數(shù)據(jù)結(jié)構(gòu)
將敏感詞轉(zhuǎn)換成樹(shù)結(jié)構(gòu),舉例敏感詞有著這么幾個(gè) ['日本鬼子','日本人','日本男人'] ,那么數(shù)據(jù)結(jié)構(gòu)如下(圖片引用參考文章)
每個(gè)文字是一個(gè)節(jié)點(diǎn),連續(xù)的節(jié)點(diǎn)組成一個(gè)詞, 日本人 對(duì)應(yīng)的就是中間的那條鏈,我們可以使用對(duì)象或者map來(lái)構(gòu)建樹(shù),這里的栗子采用 map 構(gòu)建節(jié)點(diǎn),每個(gè)節(jié)點(diǎn)中有個(gè)狀態(tài)標(biāo)識(shí),用來(lái)表示當(dāng)前節(jié)點(diǎn)是不是最后一個(gè),每條鏈路必須要有個(gè)終點(diǎn)節(jié)點(diǎn),先來(lái)看下構(gòu)建節(jié)點(diǎn)的流程圖
判斷邏輯
先從文本的第一個(gè)字開(kāi)始檢查,比如 你我是日本鬼子 ,第一個(gè)字 你 ,在樹(shù)的第一層找不到這個(gè)節(jié)點(diǎn),那么繼續(xù)找第二個(gè)字,到了 日 的時(shí)候,第一層節(jié)點(diǎn)找到了,那么接著下一層節(jié)點(diǎn)中查找 本 ,同時(shí)判斷這個(gè)節(jié)點(diǎn)是不是結(jié)尾節(jié)點(diǎn),若是結(jié)尾節(jié)點(diǎn),則匹配成功了,反之繼續(xù)匹配
代碼實(shí)現(xiàn)
####構(gòu)造數(shù)據(jù)結(jié)構(gòu)
/**
* @description
* 構(gòu)造敏感詞map
* @private
* @returns
*/
private makeSensitiveMap(sensitiveWordList) {
// 構(gòu)造根節(jié)點(diǎn)
const result = new Map();
for (const word of sensitiveWordList) {
let map = result;
for (let i = 0; i < word.length; i++) {
// 依次獲取字
const char = word.charAt(i);
// 判斷是否存在
if (map.get(char)) {
// 獲取下一層節(jié)點(diǎn)
map = map.get(char);
} else {
// 將當(dāng)前節(jié)點(diǎn)設(shè)置為非結(jié)尾節(jié)點(diǎn)
if (map.get('laster') === true) {
map.set('laster', false);
}
const item = new Map();
// 新增節(jié)點(diǎn)默認(rèn)為結(jié)尾節(jié)點(diǎn)
item.set('laster', true);
map.set(char, item);
map = map.get(char);
}
}
}
return result;
}
最終map結(jié)構(gòu)如下
查找敏感詞
/**
* @description
* 檢查敏感詞是否存在
* @private
* @param {any} txt
* @param {any} index
* @returns
*/
private checkSensitiveWord(sensitiveMap, txt, index) {
let currentMap = sensitiveMap;
let flag = false;
let wordNum = 0;//記錄過(guò)濾
let sensitiveWord = ''; //記錄過(guò)濾出來(lái)的敏感詞
for (let i = index; i < txt.length; i++) {
const word = txt.charAt(i);
currentMap = currentMap.get(word);
if (currentMap) {
wordNum++;
sensitiveWord += word;
if (currentMap.get('laster') === true) {
// 表示已到詞的結(jié)尾
flag = true;
break;
}
} else {
break;
}
}
// 兩字成詞
if (wordNum < 2) {
flag = false;
}
return { flag, sensitiveWord };
}
/**
* @description
* 判斷文本中是否存在敏感詞
* @param {any} txt
* @returns
*/
public filterSensitiveWord(txt, sensitiveMap) {
let matchResult = { flag: false, sensitiveWord: '' };
// 過(guò)濾掉除了中文、英文、數(shù)字之外的
const txtTrim = txt.replace(/[^\u4e00-\u9fa5\u0030-\u0039\u0061-\u007a\u0041-\u005a]+/g, '');
for (let i = 0; i < txtTrim.length; i++) {
matchResult = checkSensitiveWord(sensitiveMap, txtTrim, i);
if (matchResult.flag) {
console.log(`sensitiveWord:${matchResult.sensitiveWord}`);
break;
}
}
return matchResult;
}
效率
為了看出DFA的效率,我做了個(gè)簡(jiǎn)單的小測(cè)試,測(cè)試的文本長(zhǎng)度為5095個(gè)漢字,敏感詞詞庫(kù)中有2000個(gè)敏感詞,比較的算法分別為 DFA算法 和 String原生對(duì)象提供的 indexOf API做比較
// 簡(jiǎn)單的字符串匹配-indexOf
ensitiveWords.forEach((word) => {
if (ss.indexOf(word) !== -1) {
console.log(word)
}
})
分別將兩個(gè)算法執(zhí)行100次,得到如下結(jié)果
可直觀看出, DFA 的平均耗時(shí)是在1ms左右,最大為5ms; indexOf 方式的平均耗時(shí)在9ms左右,最大為14ms,所以DFA效率上還是非常明顯有優(yōu)勢(shì)的。
總結(jié)
以上所述是小編給大家介紹的js實(shí)現(xiàn)敏感詞過(guò)濾算法及實(shí)現(xiàn)邏輯,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
- Python實(shí)現(xiàn)敏感詞過(guò)濾的4種方法
- 基于python實(shí)現(xiàn)檢索標(biāo)記敏感詞并輸出
- laravel框架實(shí)現(xiàn)敏感詞匯過(guò)濾功能示例
- python用類(lèi)實(shí)現(xiàn)文章敏感詞的過(guò)濾方法示例
- 淺談Python 敏感詞過(guò)濾的實(shí)現(xiàn)
- PHP實(shí)現(xiàn)的敏感詞過(guò)濾方法示例
- 利用Python正則表達(dá)式過(guò)濾敏感詞的方法
- Python 實(shí)現(xiàn)王者榮耀中的敏感詞過(guò)濾示例
- python 實(shí)現(xiàn)敏感詞過(guò)濾的方法
- Java實(shí)現(xiàn)DFA算法對(duì)敏感詞、廣告詞過(guò)濾功能示例
- vue實(shí)現(xiàn)檢測(cè)敏感詞過(guò)濾組件的多種思路
相關(guān)文章
Django模板繼承 extend標(biāo)簽實(shí)例代碼詳解
這篇文章主要介紹了Django模板繼承 extend標(biāo)簽實(shí)例代碼,非常不錯(cuò),具有一定的參考借鑒價(jià)值 ,需要的朋友可以參考下2019-05-05
Javascript查詢(xún)DBpedia小應(yīng)用實(shí)例學(xué)習(xí)
本文則嘗試?yán)肧PARQLWrapper.js來(lái)讀取DBpedia的數(shù)據(jù),并顯示出來(lái),感興趣的你可以參考下,或許對(duì)你有所幫助2013-03-03
javascript 獲取頁(yè)面的高度及滾動(dòng)條的位置的代碼
javascript獲取頁(yè)面的高度及滾動(dòng)條的位置的代碼,需要的朋友可以參考下。2010-05-05
JavaScript高級(jí)程序設(shè)計(jì) 讀書(shū)筆記之八 Function類(lèi)及閉包
Function類(lèi)及閉包,學(xué)習(xí)js的朋友可以參考下2012-02-02
javascript實(shí)現(xiàn)禁止復(fù)制網(wǎng)頁(yè)內(nèi)容
這篇文章主要介紹了javascript實(shí)現(xiàn)禁止復(fù)制網(wǎng)頁(yè)內(nèi)容,需要的朋友可以參考下2014-12-12
bootstrap table插件的分頁(yè)與checkbox使用詳解
這篇文章主要為大家詳細(xì)介紹了bootstrap table插件的分頁(yè)與checkbox使用詳解,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-07-07
限制textbox或textarea輸入字符長(zhǎng)度的JS代碼
textbox或textarea的輸入字符限制有很多方法,在本將為大家詳細(xì)介紹下js中時(shí)如何實(shí)現(xiàn)的,感興趣的朋友不要錯(cuò)過(guò)2013-10-10

