中文分词一直是一个看起来似乎比较神秘的东西。记得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这个示例可以,真起来肯定有问题。而且要实用,在结果准确度上还要下功能。