盘古分词是一个基于 .net framework 的中英文分词组件。主要功能
中文未登录词识别 盘古分词可以对一些不在字典中的未登录词自动识别 词频优先 盘古分词可以根据词频来解决分词的歧义问题 多元分词 盘古分词提供多重输出解决分词粒度和分词精度权衡的问题 中文人名识别 输入: “张三说的确实在理” 分词结果:张三/说/的/确实/在理/ 输入 “李三买了一张三角桌子” 分词结果:李三/买/了/一张/三角/桌子/ 强制一元分词 输入 “张三说的确实在理” 分词结果: 张(0,1)/张三(0,5)/三说的(1,1)/三(1,1)/说(2,5)/的(3,5)/确(4,1)/确实(4,5)/实(5,1)/在 (6,1)/在理(6,5)/理(7,1)/ 繁体中文分词 输入"我的選擇" 分词结果: 我/的/選擇/ 同时输出简体和繁体 输入"我的選擇" 分词结果:我(0,5)/的(1,5)/选择(2,1)/選擇(2,5)/ 中文词性输出 盘古分词可以将以登录词的中文词性输出给用户,以方便用户做进一步处理。 全角字符支持 盘古分词可以识别全角的字母和数字
在项目下新建Dict文件以及dll文件包含Lucene与盘古分词所需的组件及文件信息如图示
创建词库
#region 将数据库关键字表的数据生成到分词关键字库 /// <summary> /// 将数据库关键字表的数据生成到分词关键字库 /// </summary> public void CreateKeyWordLibrary() { try { m_Trace.Trace("CreateKeyWordLibrary m_IsRuning=" + m_IsRuning); if (m_IsRuning) return; lock (m_lock) { m_IsRuning = true; var indexPath = AppDomain.CurrentDomain.BaseDirectory + @"Configlucenedir"; var directory = FSDirectory.Open(new DirectoryInfo(indexPath), new NativeFSLockFactory()); //指定索引文件(打开索引目录) FS指的是就是FileSystem var isUpdate = IndexReader.IndexExists(directory); //IndexReader:对索引进行读取的类。该语句的作用:判断索引库文件夹是否存在以及索引特征文件是否存在。 if (isUpdate) { //同时只能有一段代码对索引库进行写操作。当使用IndexWriter打开directory时会自动对索引库文件上锁。 //如果索引目录被锁定(比如索引过程中程序异常退出),则首先解锁(提示一下:如果我现在正在写着已经加锁了,但是还没有写完,这时候又来一个请求,那么不就解锁了吗?这个问题后面会解决) if (IndexWriter.IsLocked(directory)) IndexWriter.Unlock(directory); } var writer = new IndexWriter(directory, new PanGuAnalyzer(), !isUpdate, Lucene.Net.Index.IndexWriter.MaxFieldLength.UNLIMITED); //向索引库中写索引。这时在这里加锁。 using (var bll = new WxOpenMsgManageBll()) { listKeyWord = bll.QueryWxKeyWordManage(); } m_Trace.Trace("CreateKeyWordLibrary listKeyWord=" + listKeyWord.Count.ToString()); foreach (var keyword in listKeyWord) { var doc = new Document(); //Field.Store.YES:表示是否存储原值。只有当Field.Store.YES在后面才能用doc.Get("number")取出值来.Field.Index. NOT_ANALYZED:不进行分词保存 doc.Add(new Field("WxKeyWordManageId", keyword.WxKeyWordManageId.ToString(), Field.Store.YES, Field.Index.NOT_ANALYZED)); doc.Add(new Field("ResponseType", keyword.ResponseType.ToString(), Field.Store.YES, Field.Index.NOT_ANALYZED)); //Field.Index. ANALYZED:进行分词保存:也就是要进行全文的字段要设置分词 保存(因为要进行模糊查询) //Lucene.Net.Documents.Field.TermVector.WITH_POSITIONS_OFFSETS:不仅保存分词还保存分词的距离。 doc.Add(new Field("KeyWord", keyword.KeyWord ?? "", Field.Store.YES, Field.Index.ANALYZED, Lucene.Net.Documents.Field.TermVector.WITH_POSITIONS_OFFSETS)); doc.Add(new Field("Contents", keyword.Contents ?? "", Field.Store.YES, Field.Index.NOT_ANALYZED)); doc.Add(new Field("FilePath", keyword.FilePath ?? "", Field.Store.YES, Field.Index.NOT_ANALYZED)); doc.Add(new Field("PicUrl", keyword.PicUrl ?? "", Field.Store.YES, Field.Index.NOT_ANALYZED)); doc.Add(new Field("Title", keyword.Title ?? "", Field.Store.YES, Field.Index.NOT_ANALYZED)); doc.Add(new Field("Descriptions", keyword.Descriptions ?? "", Field.Store.YES, Field.Index.NOT_ANALYZED)); doc.Add(new Field("MusicURL", keyword.MusicURL ?? "", Field.Store.YES, Field.Index.NOT_ANALYZED)); doc.Add(new Field("HQMusicUrl", keyword.HQMusicUrl ?? "", Field.Store.YES, Field.Index.NOT_ANALYZED)); doc.Add(new Field("Url", keyword.Url ?? "", Field.Store.YES, Field.Index.NOT_ANALYZED)); doc.Add(new Field("ArticleCount", keyword.ArticleCount.ToString(), Field.Store.YES, Field.Index.NOT_ANALYZED)); writer.AddDocument(doc); } writer.Close();//会自动解锁。 directory.Close();//不要忘了Close,否则索引结果搜不到 m_IsRuning = false; m_LastTime = DateTime.Now; } } catch (Exception ex) { m_Trace.Trace("CreateKeyWordLibrary Exception=" + ex); m_IsRuning = false; } } #endregion
搜索关键字
#region 搜索关键字响应信息 /// <summary> /// 搜索关键字响应信息 /// </summary> /// <param name="messager"></param> /// <returns></returns> public string SearchKeyWord(WxMessager messager) { if (string.IsNullOrWhiteSpace(messager.Content)) return ""; try { var indexPath = AppDomain.CurrentDomain.BaseDirectory + @"Configlucenedir"; var list = PanGuSplitWord(messager.Content);//对用户输入的搜索条件进行拆分。 var directory = FSDirectory.Open(new DirectoryInfo(indexPath), new NoLockFactory()); var reader = IndexReader.Open(directory, true); var searcher = new IndexSearcher(reader); var parser = new QueryParser(Lucene.Net.Util.Version.LUCENE_29, "KeyWord", new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_29)); var booleanQuery = new BooleanQuery(); foreach (string word in list)//先用空格,让用户去分词,空格分隔的就是词“计算机 专业” { var query1 = new TermQuery(new Term("KeyWord", word)); booleanQuery.Add(query1, Lucene.Net.Search.BooleanClause.Occur.SHOULD); } var collector = TopScoreDocCollector.create(1000, true); searcher.Search(booleanQuery, null, collector); var docs = collector.TopDocs(0, collector.GetTotalHits()).scoreDocs; //得到所有查询结果中的文档,GetTotalHits():表示总条数 TopDocs(300, 20);//表示得到300(从300开始),到320(结束)的文档内容. //可以用来实现分页功能 var viewModelList = new List<WxKeyWordManage>(); for (int i = 0; i < docs.Length; i++) { var keyWordManage = new WxKeyWordManage(); int docId = docs[i].doc;//得到查询结果文档的id(Lucene内部分配的id) var doc = searcher.Doc(docId);//找到文档id对应的文档详细信息 keyWordManage.ArticleCount = Convert.ToInt32(doc.Get("ArticleCount")); keyWordManage.Contents = doc.Get("Contents"); keyWordManage.Descriptions = doc.Get("Descriptions"); keyWordManage.FilePath = doc.Get("FilePath"); keyWordManage.HQMusicUrl = doc.Get("HQMusicUrl"); keyWordManage.KeyWord = doc.Get("KeyWord"); keyWordManage.MusicURL = doc.Get("MusicURL"); keyWordManage.PicUrl = doc.Get("PicUrl"); keyWordManage.ResponseType = Convert.ToInt32(doc.Get("ResponseType")); keyWordManage.Title = doc.Get("Title"); keyWordManage.Url = doc.Get("Url"); viewModelList.Add(keyWordManage); } if (viewModelList != null && viewModelList.Count > 0) { //获取到相应的数据--响应给用户 var first = viewModelList.FirstOrDefault();//根据搜索规则第一条为最佳匹配项 //0-文本1-图片2-语音3-视频4-音乐5-图文 var resp_type = first.ResponseType; switch (resp_type) { case 0://文本信息 return messager.ToTextMessageXml(first.Contents.Replace("@@H5Domain@@", AirwayKeeperModel.KTGJDomainName)); case 1://图片 string picUrl = first.PicUrl; var image = WxUpLoad(picUrl); if (!string.IsNullOrWhiteSpace(image.media_id)) return messager.ToImageMessageXml(image.media_id); break; case 2://语音 break; case 3://视频 break; case 4://音乐 break; case 5://图文 break; default: break; } } } catch (Exception ex) { m_Trace.Trace("SearchKeyWord Exception=" + ex); } return ""; } #endregion
根据搜索结果处理相关业务即可
例如
公众号消息:查一下我的积分呗?
回复内容:<a href='http://h5.ktgj.com/h5/WMyPoints'>点我查看</a>我的积分
引导用户跳转H5网页查询相关业务数据
网盘资料