segment 在 NodeJS 中的中文分词模块 - 文章教程

segment 在 NodeJS 中的中文分词模块

发布于 2020-06-15 字数 7242 浏览 1547 评论 0

本模块以 盘古分词组件 中的词库为基础, 算法设计也部分参考了盘古分词组件中的算法。

本分词模块具有以下特点:

  • 纯 JavaScript 编写,可以在任何支持 ECMAScript5 的引擎上执行(需要稍微修改部分代码)
  • 基于词性进行联想识别
  • 可使用 JavaScript 编写自定义的分词模块

1、使用方法

安装:

$ npm install segment --save

使用方法:

// 载入模块
var Segment = require('segment');
// 创建实例
var segment = new Segment();
// 使用默认的识别模块及字典,载入字典文件需要1秒,仅初始化时执行一次即可
segment.useDefault();
 
// 开始分词
console.log(segment.doSegment('这是一个基于Node.js的中文分词模块。'));

返回结果格式:

[ { w: '这是', p: 0 },
  { w: '一个', p: 2097152 },
  { w: '基于', p: 262144 },
  { w: 'Node.js', p: 8 },
  { w: '的', p: 8192 },
  { w: '中文', p: 1048576 },
  { w: '分词', p: 4096 },
  { w: '模块', p: 1048576 },
  { w: '。', p: 2048 } ]

其中 w 表示词的内容,p 表示词性(具体参考 https://github.com/leizongmin/node-segment/blob/master/lib/POSTAG.js 中的定义)

不返回词性

var text = '这是一个基于Node.js的中文分词模块。';
var result = segment.doSegment(text, {
  simple: true
});
console.log(result);

结果:

[ '这是', '一个', '基于', 'Node.js', '的', '中文', '分词', '模块', '。' ]

去除标点符号


var text = '这是一个基于Node.js的中文分词模块。';
var result = segment.doSegment(text, {
  stripPunctuation: true
});
console.log(result);

结果:


[ { w: '这是', p: 0 },
  { w: '一个', p: 2097152 },
  { w: '基于', p: 262144 },
  { w: 'Node.js', p: 8 },
  { w: '的', p: 8192 },
  { w: '中文', p: 1048576 },
  { w: '分词', p: 4096 },
  { w: '模块', p: 1048576 } ]

转换同义词

载入同义词词典:

segment.loadSynonymDict('synonym.txt');

词典格式:

什么时候,何时
入眠,入睡

在分词时设置convertSynonym=true则结果中的"什么时候"将被转换为"何时""入眠"将被转换为"入睡"

var text = '什么时候我也开始夜夜无法入睡';
var result = segment.doSegment(text, {
  convertSynonym: true
});
console.log(result);

结果:

[ { w: '何时', p: 0 },
  { w: '我', p: 65536 },
  { w: '也', p: 134217728 },
  { w: '开始', p: 4096 },
  { w: '夜夜', p: 131072 },
  { w: '无法', p: 134217728 },
  { w: '入睡', p: 4096 } ]

去除停止符

载入词典:

segment.loadStopwordDict('stopword.txt');

词典格式:

之所以
因为

在分词时设置 stripStopword=true 则结果中的 "之所以" 和 "因为" 将被去除:

var text = '之所以要编写一个纯JS的分词器是因为当时没有一个简单易用的Node.js模块';
var result = segment.doSegment(text, {
  stripStopword: true
});
console.log(result);

结果:

[ { w: '编写', p: 4096 },
  { w: '纯', p: 1073741824 },
  { w: 'JS', p: [ 16 ] },
  { w: '分词', p: 4096 },
  { w: '器' },
  { w: '当时', p: 16384 },
  { w: '没有', p: 4096 },
  { w: '简单', p: 1073741824 },
  { w: '易用' },
  { w: 'Node.js', p: 8 },
  { w: '模块', p: 1048576 } ]

2、词典格式

词典文件为纯文本文件,每行定义一个词,格式为: 词|词性|词权值 ,如:工信处|0x0020|100

词性 的定义可参考文件 https://github.com/leizongmin/node-segment/blob/master/lib/POSTAG.js

词权值 越大表示词出现的频率越高

词典文件可参考:https://github.com/leizongmin/node-segment/tree/master/dicts

3、自定义识别模块

// 载入模块
var Segment = require('segment');
// 创建实例
var segment = new Segment();
// 配置,可根据实际情况增删,详见segment.useDefault()方法
segment.use('URLTokenizer');  // 载入识别模块,详见lib/module目录,或者是自定义模块的绝对路径
segment.loadDict('dict.txt'); // 载入字典,详见dicts目录,或者是自定义字典文件的绝对路径
 
// 开始分词
console.log(segment.doSegment('这是一个基于Node.js的中文分词模块。'));

一般可通过 segment.useDefault() 来载入默认的配置,若要自定义加载,可参考 useDefault() 的代码:

segment
  // 分词模块
  // 强制分割类单词识别
  .use('URLTokenizer')            // URL识别
  .use('WildcardTokenizer')       // 通配符,必须在标点符号识别之前
  .use('PunctuationTokenizer')    // 标点符号识别
  .use('ForeignTokenizer')        // 外文字符、数字识别,必须在标点符号识别之后
  // 中文单词识别
  .use('DictTokenizer')           // 词典识别
  .use('ChsNameTokenizer')        // 人名识别,建议在词典识别之后
 
  // 优化模块
  .use('EmailOptimizer')          // 邮箱地址识别
  .use('ChsNameOptimizer')        // 人名识别优化
  .use('DictOptimizer')           // 词典识别优化
  .use('DatetimeOptimizer')       // 日期时间识别优化
 
  // 字典文件
  .loadDict('dict.txt')           // 盘古词典
  .loadDict('dict2.txt')          // 扩展词典(用于调整原盘古词典)
  .loadDict('names.txt')          // 常见名词、人名
  .loadDict('wildcard.txt', 'WILDCARD', true)   // 通配符
  .loadSynonymDict('synonym.txt')   // 同义词
  .loadStopwordDict('stopword.txt') // 停止符

自定义分词器:

segment.use({
 
  // 类型
  type: 'tokenizer',
 
  // segment.use() 载入模块,初始化时执行
  init: function (segment) {
    // segment 为当前的Segment实例
  },
 
  // 分词
  split: function (words) {
    // words 为单词数组,如:['中文', '分词']
    // 返回一个新的数组用来替换旧的数组
    return words;
  }
 
});

自定义优化器:

segment.use({
 
  // 类型
  type: 'optimizer',
 
  // segment.use() 载入模块,初始化时执行
  init: function (segment) {
    // segment 为当前的Segment实例
  },
 
  // 优化
  doOptimize: function (words) {
    // words 为分词结果的单词数组,如:[{w: '中文', p: 1048576}, {w: '分词', p: 4096}]
    // 返回一个新的数组用来替换旧的数组
    return words;
  }
 
})

分词器和优化器可参考默认模块:https://github.com/leizongmin/node-segment/tree/master/lib/module

其中 *Tokenizer 表示分词器, *Optimizer 表示优化器。

注意

请勿用此模块来对较长且无任何标点符号的文本进行分词,否则会导致分词时间成倍增加。

相关链接

如果你对这篇文章有疑问,欢迎到本站 社区 发帖提问或使用手Q扫描下方二维码加群参与讨论,获取更多帮助。

扫码加入群聊

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

目前还没有任何评论,快来抢沙发吧!

关于作者

JSmiles

生命进入颠沛而奔忙的本质状态,并将以不断告别和相遇的陈旧方式继续下去。

2583 文章
29 评论
84935 人气
更多

推荐作者

清欢

文章 1 评论 0

贱贱哒

文章 3 评论 0

悸初

文章 2 评论 0

西瓜杏

文章 0 评论 0

各自安好

文章 0 评论 0