一、分词的方法
分词的方法主要有以下几种:
1、单字切分
单字切分就是把一段文字按照每个字去建立索引。
如果用来切分“我爱你伟大的中国”,就会切成“我”,“爱”,“你”,“伟”,“大”,“的”,“中”,“国”。这种分词效率低,但也能解决一些问题,聊胜于无。
2、二分法
二分法就是把一段文字的每两个相邻的字算作一个词。同样对于上面的句子就会切成“我爱”,“爱你”,“你伟”,“伟大”,“大的”,“的中”,“中国”7个词。
3、词典法
词典法就是建立一个词典文件,然后使用词典和文字段落进行匹配,从而得出分词结果。在这种分词方法中,词典和匹配算法是关键。
做词典很容易,维护词典也不能,统计而已。
匹配算法不好办,有最大匹配和最小匹配,正向匹配和逆向匹配。二二得四,就成了“最大正向匹配”,“最大逆向匹配”,“最小正向匹配”和“最小逆向匹配”。
这四种分次发哪种最好没有定论,要根据具体文本段落而定。
4、语义法
这个方法在理论上是存在的,但从实际上讲也只是个名词。看到任何一段文字,让计算机将其正确理解出来,这个想法几乎不可能。即使是人也很难全部理解。
二、盘古分词
在.Net环境中,分词比较常用的是盘古分词,项目地址是:http://pangusegment.codeplex.com/
盘古分词词库下载地址是:http://pangusegment.codeplex.com/releases/view/47411
下载解压后如下:

- Demo.exe是分词的示例程序,用于测试分词效果。
- DictManage.exe用于词库管理。
分词测试效果就不说了,下面用一张图片来说明,如何对词库进行管理。

1、盘古分词初始设置说明
1、配置选项
盘古分词在初始化的时候,需要首先配置一些参数,这些参数可以通过MatchOptions类由代码设定,然后通过一些支持该类对象的构造方法来动态设置。
ICollection<WordInfo> words= segment.DoSegment(text); ICollection<WordInfo> words= segment.DoSegment(text, options); ICollection<WordInfo> words= segment.DoSegment(text, options, parameters);
- text 为需要分词的文本
- options 为自定义分词选项,默认为 pangu.xml 中指定的分词选项
- parameters 为分词参数,默认为 pangu.xml 中指定的分词参数
配置项列表如下:
| MatchOptions属性 | 说明 |
| ChineseNameIdentify | 是否开启中文人名识别 |
| FrequencyFirst | 词频优先 |
| MultiDimensionality | 是否开启多元分词 |
| EnglishMultiDimensionality | 英文多元分词,这个开关,会将英文中的字母和数字分开 |
| FilterStopWords | 是否过滤停用词 |
| IgnoreSpace | 是否忽略空格、回车、Tab |
| ForceSingleWord | 是否强制一元分词 |
| TraditionalChineseEnabled | 是否开启繁体中文分词 |
| OutputSimplifiedTraditional | 是否同时输出简体和繁体 |
| UnknownWordIdentify | 是否开启未登录词别 |
| FilterEnglish | 是否过滤英文,这个选项只有在过滤停用词选项生效时才有效 |
| FilterNumeric | 是否过滤数字,这个选项只有在过滤停用词选项生效时才有效 |
| IgnoreCapital | 是否忽略英文大小写 |
| EnglishSegment | 英文分词 |
| SynonymOutput | 同义词输出功能一般用于对搜索字符串的分词,不建议在索引时使用 |
| WildcardOutput | 同义词输出功能一般用于对搜索字符串的分词,不建议在索引时使用 |
| WildcardSegment | 对通配符匹配的结果分词 |
| CustomRule | 是否进行用户自定义规则匹配 |
2、配置参数
配置参数通过MatchParameter类设定,在xml里设定也可以:
| MatchParameter属性 | 说明 |
| Redundancy | 多元分词冗余度 |
| UnknowRank | 未登录词权值 |
| BestRank | 最匹配词权值 |
| SecRank | 次匹配词权值 |
| ThirdRank | 再次匹配词权值 |
| SingleRank | 强行输出的单字的权值 |
| NumericRank | 数字的权值 |
| EnglishRank | 英文词汇权值 |
| SymbolRank | 符号的权值 |
| SimplifiedTraditionalRank | 强制同时输出简繁汉字时,非原来文本的汉字输出权值。原来文本是简体,这里就是输出的繁体字的权值,反之亦然 |
| SynonymRank | 同义词权值 |
| WildcardRank | 通配符匹配结果的权值 |
| FilterEnglishLength | 过滤英文选项生效时,过滤大于这个长度的英文 |
| FilterNumericLength | 过滤数字选项生效时,过滤大于这个长度的数字 |
| CustomRuleAssemblyFileName | 用户自定义规则的配件文件名 |
| CustomRuleFullClassName | 用户自定义规则的类的完整名,即带名字空间的名称 |
默认的PanGu.xml示例如下:
<?xml version="1.0" encoding="utf-8"?>
<PanGuSettings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.codeplex.com/pangusegment">
<DictionaryPath>..Dictionaries</DictionaryPath>
<MatchOptions>
<ChineseNameIdentify>true</ChineseNameIdentify>
<FrequencyFirst>false</FrequencyFirst>
<MultiDimensionality>false</MultiDimensionality>
<FilterStopWords>true</FilterStopWords>
<IgnoreSpace>true</IgnoreSpace>
<ForceSingleWord>false</ForceSingleWord>
<TraditionalChineseEnabled>false</TraditionalChineseEnabled>
<OutputSimplifiedTraditional>false</OutputSimplifiedTraditional>
</MatchOptions>
<Parameters>
<UnknowRank>1</UnknowRank>
<BestRank>5</BestRank>
<SecRank>3</SecRank>
<ThirdRank>2</ThirdRank>
<SingleRank>1</SingleRank>
<NumericRank>1</NumericRank>
<EnglishRank>5</EnglishRank>
<SymbolRank>1</SymbolRank>
<SimplifiedTraditionalRank>1</SimplifiedTraditionalRank>
<Redundancy>0</Redundancy>
</Parameters>
</PanGuSettings>
配置项与上面两个类的属性一一对应。
2、查看分词示例
下面,先写个小Demo看看如何分词:
PanGu.Segment.Init(AppDomain.CurrentDomain.SetupInformation.ApplicationBase + "/PanGu.xml");
Segment segment = new Segment();
ICollection<WordInfo> words = segment.DoSegment("张飞武功很好");
foreach (WordInfo w in words)
{
Console.WriteLine(w.Word);
}
分词效果如下:

4、整合Lucene.net进行索引、搜索示例
下面是一个简单的示例:
static void Main(string[] args)
{
PanGu.Segment.Init(AppDomain.CurrentDomain.SetupInformation.ApplicationBase + "/PanGu.xml");
//写入数据到索引
Analyzer analyzer = new PanGuAnalyzer();
Directory directory = new RAMDirectory();
IndexWriter.MaxFieldLength maxFieldLength = new IndexWriter.MaxFieldLength(10000);
using (IndexWriter writer = new IndexWriter(directory, analyzer, maxFieldLength))
{
Document document1 = new Document();
document1.Add(new Field("Sentence", "张三是一个牛人", Field.Store.YES, Field.Index.ANALYZED));
writer.AddDocument(document1);
}
//查找
using (IndexSearcher searcher = new IndexSearcher(directory))
{
PanGuTokenizer ktTokenizer = new PanGuTokenizer();
ICollection<WordInfo> words = ktTokenizer.SegmentToWordInfos("一个");
StringBuilder result = new StringBuilder();
foreach(WordInfo word in words)
{
if (word == null)
{
continue;
}
result.AppendFormat("{0}^{1}.0", word.Word,(int)Math.Pow(3,word.Rank));
}
QueryParser queryParser = new QueryParser(Lucene.Net.Util.Version.LUCENE_30, "Sentence", new PanGuAnalyzer(true));
Query query = queryParser.Parse(result.ToString());
TopDocs docs = searcher.Search(query, null, 1000);
Document doc = searcher.Doc(docs.ScoreDocs[0].Doc);
Console.WriteLine(doc.Get("Sentence"));
}
Console.ReadKey();
}
5、盘古分词高亮组件
直接上示例:
//创建HTMLFormatter,参数为高亮单词的前后缀
PanGu.HighLight.SimpleHTMLFormatter simpleHTMLFormatter = new PanGu.HighLight.SimpleHTMLFormatter("<font color="red">", "</font>");
//创建Highlighter ,输入HTMLFormatter 和盘古分词对象Semgent
PanGu.HighLight.Highlighter highlighter = new PanGu.HighLight.Highlighter(simpleHTMLFormatter, new Segment());
//设置每个摘要段的字符数
highlighter.FragmentSize = 50;
//获取最匹配的摘要段
string ContentLighter = highlighter.GetBestFragment("一个", "张三是一个牛人");
Console.WriteLine(ContentLighter);
输出如下:

