const { Segment, Tokenizer, dicts, synonyms, stopwords, modules } = require('segmentit'); const scWords = ['硅酸盐水泥', '综合工', '铜芯', '螺纹钢', 'mm2', 'mm']; /* const buffer = readFileSync(join(__dirname, '../dict/scWords.utf8')); const dicText = buffer.toString(); export const scWords = dicText.split(/\r?\n/); */ class CusTokenizer extends Tokenizer { segment; split(words) { // 需要的话可以获取到 this.segment 里的各种信息 // const TABLE = this.segment.getDict('TABLE'); const ret = []; // 这个拦截器放在第一位,优先级最高words 一般只有一个元素 for (const word of words) { let source = word.w; for (const scWord of scWords) { if (source.includes(scWord)) { // ret.push({ w: scWord, p: TABLE[scWord].p }); ret.push({ w: scWord, p: 1000 }); // 这个p 表示词性,有值时,后一个分词器就不会再对这个词进行处理了, 对于我们使用场景来说没什么用,给个默认值就好 const reg = new RegExp(`${scWord}`, 'g'); source = source.replace(reg, ''); } } if (source) ret.push({ w: source }); } return ret; } } const useDefault = (segmentInstance) => { segmentInstance.use([CusTokenizer, ...modules]); segmentInstance.loadDict(dicts); // dicText, segmentInstance.loadSynonymDict(synonyms); segmentInstance.loadStopwordDict(stopwords); return segmentInstance; }; const segmentit = useDefault(new Segment()); const scCut = (text) => { const options = { stripPunctuation: true, simple: true }; return segmentit.doSegment(text, options); }; // 获取分词数组。 const getCutWords = (aName, aSpecs) => { const cutNames = scCut(aName); const cutSpecs = scCut(aSpecs); // 规格字符混杂,分词效果极差,使用 cutHMM()效果略好。 const rst = [...cutNames, ...cutSpecs]; return rst; } // 返回匹配数。 const getMatchCount = (aUserWords, aMatchStr) => { let count = 0; for (const word of aUserWords) { if (aMatchStr.indexOf(word) > -1) count += 1; } return count; } // 分词算法相关:别名替换。返回替换后的新字符串。 const alias = (aStr) => { if (!aStr) { return aStr; } // 替换前 const a1 = ['φ', '混凝土']; // 替换后,标准。用户自定义词库以a2中的词为标准录入。 const a2 = ['Ф', '砼']; for (const key in a1) { const patt = new RegExp(a1[key], 'g'); aStr = aStr.replace(patt, a2[key]); } return aStr; } const handelThreeWord = (word) => { function getArr(tem, list) { const nameArray = scCut(tem); // 说明是一个词 if (nameArray.length === 1) list.push(tem); } const arr = []; getArr(word[0] + word[1], arr); getArr(word[1] + word[2], arr); if (arr.length > 0) return arr; return [word]; } // 自定义特殊处理 const cusSegment = (nameArray, keyword) => { const temArr = []; for (let a of nameArray) { // 混凝土 和 砼 统一认成砼 if (a === '混凝土') a = '砼'; if (a === '砼' || a === '砖') { temArr.push(a); } else if (a.length > 1) { // 如果是三个字的词,优先识别成两个字 if (a.length === 3 && !scWords.includes(a)) { const sArr = handelThreeWord(a); temArr.push(...sArr); } else { temArr.push(a); } } } if (keyword.length === 1 && temArr.length === 0) temArr.push(keyword); return temArr; } const getWordArray = (keyword) => { let wordArray = []; if (keyword.length < 3) { // 小于3个字的直接按一个词处理 wordArray.push(keyword); } else { wordArray = scCut(keyword); } // 自定义分词特殊处理 wordArray = cusSegment(wordArray, keyword); // console.log(`分词结果:${wordArray}`); return wordArray; } module.exports = { scCut, getCutWords, getMatchCount, alias, getWordArray, };