CJK Tokenizer
英文的Tokenizer就已經有夠難寫了。再加上CJK的話,寫Tokenizer簡直就是人間地獄。
為了幫這個網站設立搜索功能,我一邊看完全沒有Documentation的Demo網站,一邊抄它的源代碼。還好最後只花了三個小時就寫好了,不算太難。
整個過程中最麻煩的莫過於搜索引擎的Tokenizer了。它預設的Tokenizer好像是以空格作為每個Token的分界,所以如果我們把一篇CJK的文章丢進Tokenizer的話,它就會把整篇文章當成一個大Token去處理。解決方法其實不難,只要把每個單字當成一個Token就可以了。雖然準確度不高,但是至少能搜索到文章。
不過,我的網站的文章不是全部都是中文。我有幾篇英文的文章,它們不適合用CJK的Tokenizer。
最後,我的Tokenizer代碼如下:
encode: str => {
// to lower case
str = str.toLowerCase()
// remove html special characters
str = str.replace(/&\w+;/g, "")
// Why are there so many types of dashes
str = str.replace(/ [-–]+ /g, " ")
// remove non-language text
str = str.replace(/[^ '\-a-zA-Z0-9\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]/g, " ")
.replace(/\s+/g, " ")
.trim()
// Extract non-english
let cjk = str.replace(/[\x00-\x7F]/g, "").trim()
// Extract English (ASCII)
let eng = str.replace(/[^\x00-\x7F]/g, " ").trim()
arr = []
if (cjk !== "") {
arr = arr.concat(cjk.split(""))
}
if (eng !== "") {
arr = arr.concat(eng.split(/\s+/g))
}
return arr
我決定結合CJK和英文的Tokenizer。不太完美,但是至少能跑。
不過,CJK Word Tokenizer應該永遠都會是未解之謎吧。(你能想像作文不用字數,而是詞語數量作標準嗎……)