最近在做一個專案,尋遍了 Node 開源社群居然沒有發現一個好用的敏感詞過濾庫,有那麼幾個庫外觀上看起來似乎還不錯,用起來卻一塌糊塗,震驚有餘,失望至極。於是花了一天時間自己擼了一個庫,庫名叫 fastscan,這是我的第一個 Node 開源專案,它也可以用於瀏覽器環境。fastscan 基於廣為人知的 ahocorasick 高效能字串匹配演算法。
演示地址:pyloque.github.com/fastscan
考慮到太多的違禁詞彙,所以縮小化顯示,縮小到讓你看不清楚。如果想看清楚一點,還是去演示地址裡面看吧。消滅敏感詞是每個公民義不容辭的責任!你不站崗我不站崗,誰保衛我們祖國誰來保衛家!讀者們你們要是敢舉報,看我不砍死你!
安裝方法
# 安裝到當前專案
npm install --save fastscan
# 寫了不少單元測試,感興趣執行一下
npm test
複製程式碼
使用方法
import FastScanner from fastscan
var words = ["今日頭條","微信", "支付寶"]
var scanner = new FastScanner(words)
var content = "今日頭條小程式終於來了,這是繼微信、支付寶、百度後,第四個推出小程式功能的App。貓眼電影率先試水,出現在今日頭條。"
var offWords = scanner.search(content)
console.log(offWords)
var hits = scanner.hits(content)
console.log(hits)
-------------
[ [ 0, '今日頭條' ], [ 15, '微信' ], [ 18, '支付寶' ], [ 53, '今日頭條' ] ]
{ '今日頭條': 2, '微信': 1, '支付寶': 1 }
複製程式碼
API
- 查詢匹配的詞彙以及所在字串的位置 search(content, option={})
- 查詢匹配詞彙的命中數量 hits(content, options={})
- 臨時動態增加詞彙,不修正其它詞彙的回溯指標 add(word)
options = {quick: false, longest: false}
複製程式碼
- quick 選項表示快速模式,匹配到一個就立即返回
- longest 表示最長模式,同一個位置出現多個詞彙(中國、中國人),選擇最長的一個(中國人)
- 預設匹配出所有的詞彙,同一個位置可能會出現多個詞彙
效能
專案程式碼使用原生的 js 實現,我開始非常擔心詞彙樹的構建速度會不會太慢。經測試後發現雖然效能不算太快,不過也不是太差,對於絕大多數專案來說已經綽綽有餘了。我分別測試了構造 20000~100000 個詞彙的樹結構,每個詞彙隨機在 10~20之間,耗時情況如下
20000 words | 385ms |
---|---|
40000 words | 654ms |
60000 words | 1108ms |
80000 words | 1273ms |
100000 words | 1659ms |
如果你的詞彙比較短小,構建樹的速度還會更快。
查詢效能我並不擔心,因為 ahocorasick 演算法在詞彙長度較短的情況下複雜度是 O(n),效能和被過濾內容的長度乘線性變化。下面我使用 100000 詞彙量構建的樹分別對 20000 ~ 100000字的內容進行了過濾,耗時情況如下
20000 words | 12ms |
---|---|
40000 words | 28ms |
60000 words | 35ms |
80000 words | 49ms |
100000 words | 51ms |
fastscan 可以做到以迅雷不及掩耳的速度掃遍一幅 10w 字的長文,10w 大概就是一部中篇小說的長度了。如果你要掃百萬字的長篇小說,那還是建議你分章分節來掃吧。
記憶體佔用也是需要考慮的點,記憶體對於 Node 程式來說本來就非常有限,如果因為敏感詞樹佔據了太大的記憶體那是非常要不得的大問題。所以我也對記憶體佔用進行了測試,下面是測試的結果
0 words | 14M |
---|---|
20000 words | 81M |
40000 words | 135M |
60000 words | 184M |
80000 words | 234M |
100000 words | 277M |
詞彙量不是太大的話,這樣的記憶體佔用還是可以接受的。如果你對記憶體佔用不滿意,那就只能使用 Node 的 C 語言擴充套件來打造更高效能的庫了,考慮到成本問題,恕我目前無能為力。
注:不得不說,node 社群釋出開源類庫太方便了,npm login && npm publish 輕鬆搞定。個人覺得這大概就是 node 輪子多的罪魁禍首。對比之前釋出 java 社群開源專案,感覺自己頭髮都快掉光了,造輪子比釋出輪子還要輕鬆。
如果讀者比較關心演算法的原理和細節,請關注我的公眾號「碼洞」,後續我會編寫相關文章來仔細講解演算法的原理,以及對 fastscan 專案程式碼的剖析。