A-A+

150行代码,搞定中文分词

2008年12月24日 未分类 暂无评论 阅读 1 次

中文分词一直是一个看起来似乎比较神秘的东西。记得java中的lucene好像自带了两个分词器。一个是按汉字分,就是一个字分成一个词。比如”我要到饭馆吃饭“,就被分成”我/要/到/饭/馆/吃/饭”.别一个是相邻的两个字分成一个词,分出来的结果是”我要/要到/到饭/饭馆/馆吃/吃饭”.然而这两种虽说在做搜索时建索引什么的操作时也是相当有用的,但是毕竟是一种权宜之计,咱不能一直停留在这个水平上。

下面是来自Rlucene的一段示例代码,154行,利用sogou的词库搞定了中文分词。代码如下:

#! /usr/bin/ruby
require “socket”
#通过网络得到分词结果
def segChinese_net(line)
@conn=TCPSocket.open(”localhost”,1099)
@conn.write(line)
line=@conn.read
return line.split(” “)
end
@f= open(”dict/sogou.txt”)
@datas=@f.read.split(”n”)
@f.close

@f2=open(”dict/firstword.txt”)
@firstwords=@f2.read.split(”n”)
@f2.close
@maintable=Hash.new()
@firstwords.each{|x|
@maintable[x]=[x]
}
@datas.each{|x|
@maintable[x[0].chr+x[1].chr+x[2].chr].push(x)
}
def segChinese(line)
temp=0
max=(line.length/3)
words=[]
while(temp
pos=temp*3
str1=line[pos].chr+line[pos+1].chr+line[pos+2].chr
str12=str1
str1234=str1
if(temp<(max-1))
str2=line[pos+3].chr+line[pos+4].chr+line[pos+5].chr
str12=line[pos].chr+line[pos+1].chr+line[pos+2].chr+line[pos+3].chr+line[pos+4].chr+line[pos+5].chr
end
if(temp<(max-3))
str1234=line[pos].chr+line[pos+1].chr+line[pos+2].chr+line[pos+3].chr+line[pos+4].chr+line[pos+5].chr+line[pos+6].chr+line[pos+7].chr+line[pos+8].chr+line[pos+9].chr+line[pos+10].chr+line[pos+11].chr
end
if(!@maintable[str1].nil?)
if(!@maintable[str1].index(str1234).nil?)
temp+=4
words.push(str1234)
else
if(!@maintable[str1].index(str12).nil?)
temp+=2
words.push(str12)
else
words.push(str1)
temp+=1
end
end
else
words.push(str1)
temp+=1
end
end
return words
end
#return an array of the segemention.
#得到当前句子的分词结果.
def segment(str)

chars=Hash.new(0)
chars["char"]=”~!@#$%^&*()_+}{[]|”‘:;/?><,. tnba”
chars["num"]=”0123456789″
chars["alpha"]=”abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ”
bytes=Hash.new(0)
i=0
buffer=”"
#oldtype 表示上一个字符的种类:字符还是字母还是数字
#newtype表示本字符的种类
#type:1,表示字符,2表示数字,3表示字母,4表示属于汉字(多字节字符)
#Buffer用来存储当未完成的一个词.
#只有当当前字符类型与前一个字符类型不一致时才输出buffer,并清空buffer,改为当前字符值.
#当与前一字符类型相同时,仅是把当前字符推入buffer(加到buffer的后面)
#oldtype为4时,当输出一个buffer时,还需要对当前buffer进行中文分词
oldtype=0
newtype=0
flag=0
words=[]
0.upto(str.length-1){|a|
if(flag>0)
flag=flag-1
else
x=str[a]
if(!chars["char"].index(x.chr).nil?)
newtype=1
if(newtype==oldtype)
buffer=buffer+x.chr
else
if(oldtype==4)
words.concat(segChinese(buffer.strip))
buffer=x.chr
else
words.push( buffer) if (buffer.strip!=”")
buffer=x.chr
end
end
oldtype=1
end
if(!chars["num"].index(x.chr).nil?)
newtype=2
if(newtype==oldtype)
buffer=buffer+x.chr
else
if(oldtype==4)
words.concat(segChinese(buffer.strip))
buffer=x.chr
else
words.push(buffer) if (buffer.strip!=”")
buffer=x.chr
end
end
oldtype=2
end
if(!chars["alpha"].index(x.chr).nil?)
newtype=3
if(newtype==oldtype)
buffer=buffer+x.chr
else
if(oldtype==4)
words.concat(segChinese(buffer.strip))
buffer=x.chr
else
words.push(buffer) if (buffer.strip!=”")
buffer=x.chr
end
end
oldtype=3
end
if(x>127)
flag=+2
newtype=4
if(newtype==oldtype)
buffer=buffer+str[a].chr+str[a+1].chr+str[a+2].chr
else
words.push(buffer) if(buffer.strip!=”")
buffer=str[a].chr+str[a+1].chr+str[a+2].chr
end
oldtype=4
end
end
}
if(oldtype==4)
words.concat(segChinese(buffer.strip))
else
words.push(buffer) if(buffer.strip!=”")
end
total=”"
words.each{|x| total=total+x+” “}
return total
#puts total
end

ruby果然就是牛B极了。在学着用BCB折腾nsapi的时候 ,发现了asp,于是我觉得asp真是一个比较牛B的东西。接着发现了php,于是我扔掉了asp, 接着发现python比php有前途,现在,python还没摸透,又瞅 上ruby了。世界变化真是太快了,我快跟不上啦。

不过要实用,可能还得做些调整。 一般来说,分词的词库得自己整,sogou这个示例可以,真起来肯定有问题。而且要实用,在结果准确度上还要下功能。

给我留言

Copyright © 浩然东方 保留所有权利.   Theme  Ality 07032740

用户登录