分词对于搜索引擎,输入法输入提示,语音识别等其它人机交互系统等都很有用。互联网的海量信息为分词研究提供了大量的,动态更新的原始资料库。很多互联网公司都有基于互联网内容的分词系统。并且采用HADOOP等分析大量数据。这些听上去很高大上,但是仔细想想基本原理应该是比较容易理解的,我们每个程序员也很容易可以研究这个领域。所以做了一个简单的POC实验。
首先写一个Spider,从互联网页面抓取内容。因为只是简单实验,我只抓取一个页面,没有做递归抓取链接页面。抓取内容过滤掉HTML标签留下纯文本。
第二部分,写一个字之间连续出现频率分析的分析器。基本思想是,定义一个已读字符缓存区,读取输入字符流,对每个字X:
1 . 如果是空格等分隔字符,则清空缓存。
2. 如果是正常字符:如果缓存已经有内容E则记录<E, X>匹配次数加一。然后将X也放入缓存。(问题:应该对于E的任意后子串都可以基数加一。)
这样,最终我们可以得出每个字符串后面跟随的可能字符的列表和对应的匹配次数。在这个实验里,我用文件系统的目录结构来记录:每个字符串一个文件夹,然后后面可能出现的每个词一个文件,文件是空的,用文件的lastModified时间戳记录匹配次数。这在一个真正的系统里是不可行的,必须设计存储数据结构;但是为了简单期间,我们在这个实验里就利用文件系统。
第三部分是做一个Java Swing界面,给一个输入框,用户输入任意字符串,然后根据用户输入找出最常匹配的下个字符。这里有几个问题:
1. 只找一个字符不太够,比如用户输入 【中华人民】,我们应该给出【共和国】而不是只提示一个【共】。所以在匹配一个后,需要在此基础上给出下一个匹配字符。
2. 如果对用户输入无法匹配到下一个字符,则应该去掉用户输入串最左边的字符,根据右边字串继续匹配,并递归,直到找到匹配或者字串长度为零。(由于我们记录所有的可能,实际上当可能性小于某值时应该认为不再是以后词。)
3. 上边两种情况一起考虑时,不能弄混,比如不能匹配处一个连续但是无意义的单字接龙,比如 【中国家人民兵种子】,所以匹配下一个字时要考虑整个前面的分词,要不要继续找下一个可能字符。这里情况稍微复杂。在这个简单实验里只是简单处理了一下。
总的来说,这个小实验给出了比较有意义的结果。当然在一个真正的产品里要对更多的相关问题做研究。
代码在这里: http://blog.luoxq.com/files/fenci.tar 一共只有200+行代码。
界面现实结果如下: