敏感詞過濾算法實現
說到敏感詞過濾,我也覺得這里沒有必要寫這個文章,因為前人已經前前后后有過很多種算法解決該問題。這里我之所以寫這個文章,是因為我自己自創了一種算法(真的是自創哦,因為我在寫這個算法的時候,完全是自己想出來的方式,沒有借鑒任何代碼!靈感來自于一篇文章中的一句話“如果能掃描一遍文本就能將所有的詞找出來,那速度就是最快的”)。想法不周到或想得不周到,請大家磚頭輕拍
背景
在網絡日益發達的現在,也伴隨著有益信息與造成不穩定因素的信息也隨之日益泛濫,為了網民的思想健康,也為了社會的和諧,在許多對外公共場合下,有些內容是要經過審查才能顯示的。在網絡審查初期,都是通過人工審核,這種審核方式雖然準確且智能,但與網絡文字產生的速度相比,其效率就顯示微不足道了!因此,自動化的系統處理方式的需求越來越強烈……
目前擁有的處理方式
有需求就有市場,因此自動化處理的方式自然而然隨之如雨后春筍般地迅速產生了一大批!其處理方式都是基于一點:敏感詞庫!然后基于該詞庫對目標文本進行敏感詞提取操作,因此各自動化處理方式的唯一差別就在于敏感詞提取算法的不同,因為算法不同,效率不同、結果也可能不同。而對于敏感詞過濾算法來說,要掌握兩個關鍵點:效率和準確率!效率就是對于大批量敏感詞和長段的目標文本處理時要能在很短時間內響應;準確率就是對于一個敏感詞要盡量區分語境,不能誤將非敏感詞判斷為敏感詞而過濾掉(如我們敏感詞庫的精確匹配與模糊匹配的定義)!
就我所知,目前較為流行且成熟的算法有:
簡單文本搜索與替換
這種方式是最簡單的,就是循環把每個敏感詞在目標文本中從頭到尾搜索一遍,如果有文本高亮或替換的話,那就找到一個就處理一個。這種方式的優缺點如下:
優點:
- 算法簡單。對于開發人員來說,簡單的算法會使代碼實現上簡單,開發難度最小!
缺點:
- 效率太低。因為循環每個敏感詞,所以當敏感詞很多、目標文本很長時,其效率可以說是該算法的致命問題!
- 匹配準備率太低。比如,有一個敏感詞為as,那它邊hash、class等中的as都會被匹配甚至被處理。
所以這個算法絕對不能使用!
傳說中的DFA算法(亦稱自動機算法)
上面的算法是以敏感詞庫為主體,對目標文本進行匹配,而這個算法是以目標文本為主體,其算法大概為:將所有敏感詞構建為詞圖(即是將所有敏感詞組織為一個圖狀關系,即,以任意一個字都可以查出以該字為開頭的詞),然后對文本進行逐一搜索并看每個字是否在圖中存在,如果存在看是否有對應的詞存在,如果存在,則匹配成功,記錄下來,繼續往下搜索直到搜索完整個文本!其詳細的算法原理參見:http://wenku.baidu.com/view/2e9dad18a8114431b90dd896.html。
優點:
- 效率高于上面的算法;
缺點:
- 理論算法太過復雜,開發成本很大,而且網上沒有該算法的源碼或相應的包!而且該算法匹配率也比較低。再者就是該算法巨耗內存,而且啟動很慢。
網友自創的TTMP算法(自稱 字符串多模式精確匹配)
其算法主要原理為:
1、首先掃描文章里面的每一個字符,只有當某一個字符是臟字表中任意一個臟詞的第一個字符(稱為“起始符”),我們才試圖看看接下來是否是臟字(觸發檢索)。
2、但是我們也不是毫無頭緒的就開始循環臟字表的每一個詞條:
2.1、我們往后檢索一個字符,先看一下這個字符是否是臟字表里面的任意一個字符,如果不是,就表明不可能是臟字表中的任何一個條目,就可以退出了。
2.2、如果是,我們就取從第一個被檢出字符到目前掃描到的字符之間的字符串,求哈希值,看看能否從哈希表中檢出一個臟詞。
如果檢出了,那就大功告成,否則繼續檢索后面一個字符(重復2.1、2.2),直至找不到,或者超出臟字表條目最大的長度。
2.3、如果都找不到,或者超長,那么接下來就回到剛才的那個“起始符”后一個字符繼續掃描(重復1、2),直至整個文章結束。
詳細的算法說明參考:http://www.cnblogs.com/sumtec/archive/2008/02/01/1061742.html。
其它可查算法
其它查到的算法還有:KMP算法是單模匹配算法,BM據說也是單模式的算法,WM算法是多模匹配……好吧,我承認,到最后的時候,我沒有耐心再看下去了,因為這些算法都說自己很厲害,可是卻都沒有放出具體完整的可用的算法程序出來!開發難度還是存在的,這些方法都不是我的菜
我設想的一個算法——基于分詞組件結合向量相似運算
在無盡的苦海探尋的過程中,我的大學數學知識不斷滴從的我意識深處涌了出來!我突然想起一個可能可行的辦法:因為網絡上有許多性能很不錯的分詞工具(jar包形式的也大有存在),而且大學時有一種向量算法可以計算兩個向量間的相似度的能力,于是就想到是否可以使用向量算法來解決該問題。該算法的主體思想為:將所有敏感詞構建為一個向量,再將目標文本用分詞工具分成若干個詞并構建成另一個向量,然后將這兩個向量進行相似值計算,得出哪些向量元素相同,并最終得知該目標文本中存在哪些敏感詞!
呃……看來我還是對不起祖國對不起黨!我已經不記得相應的向量算法了,而且也沒有找到一個計算兩個向量元素之間相同的算法(因為向量的高級算法太多、太復雜了)!看來從我意識深處涌出來的只是一些影子~
所以,這只是一個設想,而非真正實現方案!
敏感詞過濾算法(自命名:聚合詞樹查詢法)
該算法基于DFA并結合許多算法并進行相應的簡化,最終其算法基本原理為:將所有敏感詞庫按模塊聚合構建成一個詞樹(所謂聚合,就是將相同字開頭的部分進行聚合,以減少對詞的查詢范圍,相當于建立敏感詞索引,如:他奶奶的、他媽的、他娘的,這三個詞,聚合構建成詞樹時,“他”字就是這三個詞的索引,同時每個詞的結尾都有一個結束標志和該詞的一些描述,如敏感級別等),然后從頭到尾掃描一遍目標文本,當遇到以敏感詞樹中的索引的字時,查看后面的文本是否構成敏感詞(如果這里有以這個敏感詞開頭的更長的敏感詞時,以更長的為匹配結果,并判斷該詞在文本中前后是否有分隔符來區別其匹配方式),如果是則記錄,一遍掃描完之后所有敏感詞即被掃描出來了!
結語
我的這個算法不一定是最好的,但相比較上面幾種算法,從成本、效果等整體上來說是很合適的!另外網上還有許多一些未公開算法的過濾方式,這些算法因為無法獲知其算法,而無法為我所借鑒,因此平添幾許遺憾!另外還有著名的算法有:KMP算法是單模匹配算法,BM據說也是單模式的算法,WM算法是多模匹配(WM算法詳細描述:http://blog.chinaunix.net/space.php?uid=20435679&do=blog&cuid=228430)的等等。
該方法還有許多可優化的空間,如可增加多線程、可優化判斷已記錄的詞直接跳過不匹配等方式。
算法的效率要注意盡量滿足兩點:盡量少的掃描目標文本(包括盡量少的回掃目標文本),盡快能從敏感詞庫中找到指定的詞!不斷做到這兩點,則效率就越高!
效率上還有提升空間
目前只是單線程的一種操作,而且算法實現的代碼上可能還有一些小小的改進余地,如變量定義與數據結構的定義等方面的實現。
匹配能力較弱
不能對處理的關鍵詞匹配,比如,“鴉 片”是一個敏感詞的話,那如果用戶刻意把它們分開,如寫成“鴉$片”,那就無法匹配上了!
還可以運用于很多場景
運用的場景很多,如高亮指定的詞、分詞(可以指定以最長或最短模式匹配)、拼音與漢字間的轉換等等字符串匹配功能!
注:附件中有兩個文件,一個ppt,用于演示該算法的過程(用office2007打開效果最佳);一個是源代碼;請大家自己瀏覽,謝謝!