Golang写的中文分词开发包。
参考sego
两个重要方法// Dictionary结构体实现了一个字串前缀树,
// 一个分词可能出现在叶子节点也有可能出现在非叶节点
type Dictionary struct {
root node // 根节点
maxTokenLength int // 词典中最长的分词
numTokens int // 词典中分词数目
tokens []*Token // 词典中所有的分词,方便遍历
totalFrequency int64 // 词典中所有分词的频率之和
}
// 前缀树节点
type node struct {
word Text // 该节点对应的字元
token *Token // 当此节点没有对应的分词时值为nil
children []*node // 该字元后继的所有可能字元,当为叶子节点时为空
}
//分词器结构体
type Segmenter struct {
dict *Dictionary
}
// 字典加载方法
// 可以载入多个词典文件,文件名用","分隔,排在前面的词典优先载入分词,比如
// "用户词典.txt,通用词典.txt"
// 当一个分词既出现在用户词典也出现在通用词典中,则优先使用用户词典。
// 词典的格式为(每个分词一行):
// 分词文本 频率 词性
func (self * Segmenter) LoadDictionary(files string)
// 对文本分词
// 输入参数:
// bytes UTF8文本的字节数组
// 输出:
// []Segment 划分的分词
func (self *Segmenter) Go(bytes []byte, model bool) []Segment
/*
cut 分词服务器提供JSON格式的RPC服务
datatime: 2015-10-12
author: aosen
homepage: https://github.com/aosen/
url:
"/"
输入:
GET模式输入text参数
输出:
{
result:[
{"text":"服务器", "pos":"n"},
{"text":"指令", "pos":"n"},
...
],
err: 0,
errmsg: ""
}
*/
package main
import (
"encoding/json"
"flag"
"fmt"
"github.com/aosen/cut"
"io"
"log"
"net/http"
"strings"
)
var (
host = flag.String("host", "127.0.0.1", "HTTP服务器主机名")
port = flag.Int("port", 2019, "HTTP服务器端口")
dict = flag.String("dict", "dict.txt", "词典文件")
//生成分词器对象
segmenter = cut.Segmenter{}
)
/*返回的JSON数据*/
type Response struct {
Values []*Value `json:"result"`
Err int `json:"err"`
Errmsg string `json:"errmsg"`
}
type Value struct {
Text string `json:"text"`
Pos string `json:"pos"`
}
var ERR = map[int]string{
0: "success",
500: "Invalid argument",
}
func JsonRpcServer(w http.ResponseWriter, req *http.Request) {
//结果处理
JsonResponse := func(v []*Value, code int) {
resp, _ := json.Marshal(&Response{
Values: v,
Err: code,
Errmsg: ERR[code],
})
//w.Header().Set("Content-Type", "application/json")
io.WriteString(w, string(resp))
}
//通用处理方法
handle := func(text string, mode string) {
if text == "" || (!strings.EqualFold(mode, "1") && !strings.EqualFold(mode, "0")) {
JsonResponse(nil, 500)
} else {
//整理为输出格式
s := []*Value{}
//开始分词
func() {
for _, seg := range segmenter.Go([]byte(text),
func() bool {
if mode == "1" {
return true
} else {
return false
}
}()) {
s = append(s, &Value{
Text: seg.Token().Text(),
Pos: seg.Token().Pos(),
})
}
}()
JsonResponse(s, 0)
}
}
// 得到要分词的文本
if req.Method == "GET" {
text := req.URL.Query().Get("text")
mode := req.URL.Query().Get("mode")
handle(text, mode)
} else if req.Method == "POST" {
text := req.PostFormValue("text")
mode := req.PostFormValue("mode")
handle(text, mode)
}
}
func main() {
flag.Parse()
//初始化分词器
segmenter.LoadDictionary(*dict)
http.HandleFunc("/", JsonRpcServer)
log.Printf("cut server run on %s:%d", *host, *port)
http.ListenAndServe(fmt.Sprintf("%s:%d", *host, *port), nil)
}