UNPKG

12.8 kBMarkdownView Raw
1[![jetbrains.svg](jetbrains.svg)](https://www.jetbrains.com/?from=novel-segment)
2
3# 中文分词模块
4
5 Chinese word segmentation 簡繁中文分词模块 以網路小說為樣本
6
7本模块以**[盘古分词组件](http://pangusegment.codeplex.com/)**中的词库为基础,
8算法设计也部分参考了盘古分词组件中的算法。
9
10本分词模块具有以下特点:
11
12+ 纯JavaScript编写,可以在任何支持ECMAScript5的引擎上执行(需要稍微修改部分代码)
13+ 基于词性进行联想识别
14+ 可使用JavaScript编写自定义的分词模块
15
16Fork From [leizongmin/segment](https://github.com/leizongmin/node-segment)
17
18---
19
201. 以網路翻譯小說為樣本增加字典
212. 可緩存字典數據讓下次使用勉強快一丁點
223. 可啟用自動將字典無視簡繁日漢字
234. 精簡一部分多餘字典
245. 可額外追加字典條目而不需要增加字典檔
256. 可將結果轉換為原始格式
267. 遇到長句,無分段,無標點符號的行時會捨棄部分處理,來避免處理時間過長過超過記憶體負荷<br/>可於啟動 nodejs 時 加上參數 例如 `node --max-old-space-size=2048 xxxx.js` 可以避免記憶體洩漏問題
278. 與原版不同預設會返回所有字元(包含分行與空格)
28
29* [線上測試 by RunKit](https://npm.runkit.com/novel-segment)
30
31## live demo
32
33> https://segment-api.bluelovers.now.sh/demo.html
34
35### api
36
37```
38https://segment-api.bluelovers.now.sh/conv?input=从时间上来说是过了数秒。视线的焦点总算稳定后,那是在顶棚略低的运动跑车的右边驾驶席上。稳稳坐在车内驾驶席上的要,朝着映在车内镜的脸庞望去。柔顺的黑发加上好战的锐利目光,穿在身上的松垮衬衫被卷起了袖子,系在脖子上的红色领带显得极为松垮。把视线落到双手上,带着手表的手腕下是不怎么厚的蓝色裤子,腿上还挂着黑色的随身包。一瞬间脑子还有点没转过来,之后总算理解了情况。
39```
40
41```
42https://segment-api.bluelovers.now.sh/?input=从时间上来说是过了数秒。视线的焦点总算稳定后,那是在顶棚略低的运动跑车的右边驾驶席上。稳稳坐在车内驾驶席上的要,朝着映在车内镜的脸庞望去。柔顺的黑发加上好战的锐利目光,穿在身上的松垮衬衫被卷起了袖子,系在脖子上的红色领带显得极为松垮。把视线落到双手上,带着手表的手腕下是不怎么厚的蓝色裤子,腿上还挂着黑色的随身包。一瞬间脑子还有点没转过来,之后总算理解了情况。
43```
44
45**歡迎一同來追加字典**
46
47* [segment-dict](https://github.com/bluelovers/ws-segment/tree/master/packages/segment-dict) - dictionary data
48
49### TODO
50
51> 以下功能距離實現可能遙遙無期
52
531. 追加支援常見混雜於中文內的英文辭典
54
55## Breaking Changes
56
57請注意 從 2.0.0 版之後 開始 更改了 synonym 字典的格式
58
59* 原版為一對一 => 錯字,正字
60* 這裡為一對多 並且順序與原版相反 => 正字,錯字,...以,分隔更多字
61
62請注意 從 2.2.0 版之後 開始 更改了分詞算法
63
64* 當分詞得分相同時會以先出現的結果為優先
65* 修正語法計算錯誤 { `形容詞 + 動詞` => `副詞 + 動詞` }
66
67
68## 安装
69
70```bash
71npm install novel-segment
72```
73
74* npm: [novel-segment](https://www.npmjs.com/package/novel-segment)
75* github: [novel-segment](https://github.com/bluelovers/ws-segment/tree/master/packages/novel-segment)
76
77## demo
78
79以下範例已經自動啟用以下功能
80
81* 新增字典項目時自動補充繁簡日的異體漢字
82* 啟用 ZhtSynonymOptimizer 模組
83* 緩存功能
84
85* [demo.glob.ts](https://github.com/bluelovers/ws-segment/tree/master/packages/node-segment/tree/master/test/demo.glob.ts)
86* [demo.cache.ts](https://github.com/bluelovers/ws-segment/tree/master/packages/node-segment/tree/master/test/demo.cache.ts)
87
88可搭配其他繁簡轉換程式使用
89
90* [線上測試 by RunKit](https://npm.runkit.com/novel-segment)
91
92## API
93
94* [API](docs)
95* [其他雜項 Readme](https://github.com/bluelovers/ws-segment/tree/master/packages/novel-segment/tree/master/demo)
96* [Segment.d.ts](https://github.com/bluelovers/ws-segment/tree/master/packages/novel-segment/tree/master/lib/Segment.d.ts)
97* [POSTAG.ts](https://github.com/bluelovers/ws-segment/tree/master/packages/novel-segment/tree/master/lib/POSTAG.ts)
98* [segment-dict](https://github.com/bluelovers/ws-segment/tree/master/packages/segment-dict) - 字典 dictionary data
99
100### 特點模組
101
102* [ZhtSynonymOptimizer.ts](https://github.com/bluelovers/ws-segment/tree/master/packages/novel-segment/tree/master/lib/submod/ZhtSynonymOptimizer.ts) - 基於語意來修正各種需要人工修正的詞彙 例如 `里后`...等等 (預設不啟用 因為這與分詞無關)
103* [JpSimpleTokenizer.ts](https://github.com/bluelovers/ws-segment/tree/master/packages/novel-segment/tree/master/lib/submod/JpSimpleTokenizer.ts) 簡易的日文切割 (預設啟用)
104* [ForeignOptimizer.ts](https://github.com/bluelovers/ws-segment/tree/master/packages/novel-segment/tree/master/lib/submod/ForeignOptimizer.ts) 合併外文與中文混雜的詞 (預設啟用)
105
106## 1、使用方法
107
108使用方法:
109
110```javascript
111// 载入模块
112var Segment = require('novel-segment');
113// 创建实例
114var segment = new Segment();
115// 使用默认的识别模块及字典,载入字典文件需要1秒,仅初始化时执行一次即可
116segment.useDefault();
117
118// 开始分词
119console.log(segment.doSegment('这是一个基于Node.js的中文分词模块。'));
120```
121
122返回结果格式:
123
124```javascript
125[ { w: '这是', p: 0 },
126 { w: '一个', p: 2097152 },
127 { w: '基于', p: 262144 },
128 { w: 'Node.js', p: 8 },
129 { w: '的', p: 8192 },
130 { w: '中文', p: 1048576 },
131 { w: '分词', p: 4096 },
132 { w: '模块', p: 1048576 },
133 { w: '。', p: 2048 } ]
134```
135其中 `w` 表示词的内容,`p` 表示词性(具体参考 https://github.com/bluelovers/node-segment/blob/master/lib/POSTAG.ts 中的定义)
136
137### 不返回词性
138
139```javascript
140var text = '这是一个基于Node.js的中文分词模块。';
141var result = segment.doSegment(text, {
142 simple: true
143});
144console.log(result);
145```
146
147结果:
148
149```javascript
150[ '这是', '一个', '基于', 'Node.js', '的', '中文', '分词', '模块', '。' ]
151```
152
153### 去除标点符号
154
155```javascript
156var text = '这是一个基于Node.js的中文分词模块。';
157var result = segment.doSegment(text, {
158 stripPunctuation: true
159});
160console.log(result);
161```
162
163结果:
164
165```javascript
166[ { w: '这是', p: 0 },
167 { w: '一个', p: 2097152 },
168 { w: '基于', p: 262144 },
169 { w: 'Node.js', p: 8 },
170 { w: '的', p: 8192 },
171 { w: '中文', p: 1048576 },
172 { w: '分词', p: 4096 },
173 { w: '模块', p: 1048576 } ]
174```
175
176### 转换同义词
177
178载入同义词词典:
179
180```javascript
181segment.loadSynonymDict('synonym.txt');
182```
183
184词典格式:
185
186```
187什么时候,何时
188入眠,入睡
189```
190
191在分词时设置`convertSynonym=true`则结果中的`"什么时候"`将被转换为`"何时"``"入眠"`将被转换为`"入睡"`
192
193```javascript
194var text = '什么时候我也开始夜夜无法入睡';
195var result = segment.doSegment(text, {
196 convertSynonym: true
197});
198console.log(result);
199```
200
201结果:
202
203```javascript
204[ { w: '何时', p: 0 },
205 { w: '我', p: 65536 },
206 { w: '也', p: 134217728 },
207 { w: '开始', p: 4096 },
208 { w: '夜夜', p: 131072 },
209 { w: '无法', p: 134217728 },
210 { w: '入睡', p: 4096 } ]
211```
212
213### 去除停止符
214
215载入词典:
216
217```javascript
218segment.loadStopwordDict('stopword.txt');
219```
220
221词典格式:
222
223```
224之所以
225因为
226```
227
228在分词时设置`stripStopword=true`则结果中的`"之所以"``"因为"`将被去除:
229
230```javascript
231var text = '之所以要编写一个纯JS的分词器是因为当时没有一个简单易用的Node.js模块';
232var result = segment.doSegment(text, {
233 stripStopword: true
234});
235console.log(result);
236```
237
238结果:
239
240```javascript
241[ { w: '编写', p: 4096 },
242 { w: '纯', p: 1073741824 },
243 { w: 'JS', p: [ 16 ] },
244 { w: '分词', p: 4096 },
245 { w: '器' },
246 { w: '当时', p: 16384 },
247 { w: '没有', p: 4096 },
248 { w: '简单', p: 1073741824 },
249 { w: '易用' },
250 { w: 'Node.js', p: 8 },
251 { w: '模块', p: 1048576 } ]
252```
253
254
255## 2、词典格式
256
257词典文件为纯文本文件,每行定义一个词,格式为: `词|词性|词权值` ,如:`工信处|0x0020|100`
258
259**词性** 的定义可参考文件 https://github.com/bluelovers/node-segment/blob/master/lib/POSTAG.ts
260
261**词权值** 越大表示词出现的频率越高
262
263词典文件可参考:https://github.com/bluelovers/node-segment/tree/master/dicts
264
265
266## 2、自定义识别模块
267
268```javascript
269// 载入模块
270var Segment = require('novel-segment');
271// 创建实例
272var segment = new Segment();
273// 配置,可根据实际情况增删,详见segment.useDefault()方法
274segment.use('URLTokenizer'); // 载入识别模块,详见lib/module目录,或者是自定义模块的绝对路径
275segment.loadDict('dict.txt'); // 载入字典,详见dicts目录,或者是自定义字典文件的绝对路径
276
277// 开始分词
278console.log(segment.doSegment('这是一个基于Node.js的中文分词模块。'));
279```
280
281一般可通过 `segment.useDefault()` 来载入默认的配置,若要自定义加载,可参考 `useDefault()` 的代码:
282
283```javascript
284segment
285 // 分词模块
286 // 强制分割类单词识别
287 .use('URLTokenizer') // URL识别
288 .use('WildcardTokenizer') // 通配符,必须在标点符号识别之前
289 .use('PunctuationTokenizer') // 标点符号识别
290 .use('ForeignTokenizer') // 外文字符、数字识别,必须在标点符号识别之后
291 // 中文单词识别
292 .use('DictTokenizer') // 词典识别
293 .use('ChsNameTokenizer') // 人名识别,建议在词典识别之后
294
295 // 优化模块
296 .use('EmailOptimizer') // 邮箱地址识别
297 .use('ChsNameOptimizer') // 人名识别优化
298 .use('DictOptimizer') // 词典识别优化
299 .use('DatetimeOptimizer') // 日期时间识别优化
300
301 // 字典文件
302 .loadDict('dict.txt') // 盘古词典
303 .loadDict('dict2.txt') // 扩展词典(用于调整原盘古词典)
304 .loadDict('names.txt') // 常见名词、人名
305 .loadDict('wildcard.txt', 'WILDCARD', true) // 通配符
306 .loadSynonymDict('synonym.txt') // 同义词
307 .loadStopwordDict('stopword.txt') // 停止符
308```
309
310自定义分词器:
311
312```javascript
313segment.use({
314
315 // 类型
316 type: 'tokenizer',
317
318 // segment.use() 载入模块,初始化时执行
319 init: function (segment) {
320 // segment 为当前的Segment实例
321 },
322
323 // 分词
324 split: function (words) {
325 // words 为单词数组,如:['中文', '分词']
326 // 返回一个新的数组用来替换旧的数组
327 return words;
328 }
329
330});
331```
332
333自定义优化器:
334
335```javascript
336segment.use({
337
338 // 类型
339 type: 'optimizer',
340
341 // segment.use() 载入模块,初始化时执行
342 init: function (segment) {
343 // segment 为当前的Segment实例
344 },
345
346 // 优化
347 doOptimize: function (words) {
348 // words 为分词结果的单词数组,如:[{w: '中文', p: 1048576}, {w: '分词', p: 4096}]
349 // 返回一个新的数组用来替换旧的数组
350 return words;
351 }
352
353})
354```
355
356分词器和优化器可参考默认模块:https://github.com/bluelovers/node-segment/tree/master/lib/module
357
358其中 `*Tokenizer` 表示分词器, `*Optimizer` 表示优化器。
359
360
361## 注意
362
363**请勿用此模块来对较长且无任何标点符号的文本进行分词,否则会导致分词时间成倍增加。**
364
365
366## MIT License
367
368```
369Copyright (c) 2012-2015 Zongmin Lei (雷宗民) <leizongmin@gmail.com>
370http://ucdok.com
371
372The MIT License
373
374Permission is hereby granted, free of charge, to any person obtaining
375a copy of this software and associated documentation files (the
376"Software"), to deal in the Software without restriction, including
377without limitation the rights to use, copy, modify, merge, publish,
378distribute, sublicense, and/or sell copies of the Software, and to
379permit persons to whom the Software is furnished to do so, subject to
380the following conditions:
381
382The above copyright notice and this permission notice shall be
383included in all copies or substantial portions of the Software.
384
385THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
386EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
387MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
388NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
389LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
390OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
391WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
392```
393