本文参考自:https://blog.csdn.net/mss359681091/article/details/52078147

      http://www.cnblogs.com/top5/archive/2011/08/18/2144030.html

本文所有需要用到的文件下载包含项目:

Lucene配置文件下载

中文分词配置文件下载

本文项目下载Zip

1.一元分词  / 2.二元分词 / 3.盘古分词 / 4.中文分词 / 5.简单搜索

用vs2015创建Windows窗体应用程序,创建好项目时记得将其属性改为“控制台应用程序”,当然也可以是默认的,只是这样方便些。如下图

1.一元分词法

除此外,还需要引用’Lucene.Net.dll‘

 /// <summary>
/// 一元分词法
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button1_Click(object sender, EventArgs e)
{
Analyzer analyzer = new StandardAnalyzer(); // 标准分词 → 一元分词
TokenStream tokenStream = analyzer.TokenStream("", new StringReader("喝奶只喝纯牛奶,这是不可能的——黑夜中的萤火虫"));
Token token = null;
while ((token = tokenStream.Next()) != null) // 只要还有词,就不返回null
{
string word = token.TermText(); // token.TermText() 取得当前分词
Console.Write(word + " | ");
}
}

一元分词法

2.二元分词法

在刚才的基础上,再引用文件夹“Analyzers”中的两个.cs文件,如下图

 /// <summary>
/// 二元分词
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button2_Click(object sender, EventArgs e)
{
Analyzer analyzer = new CJKAnalyzer(); // 标准分词 → 一元分词
TokenStream tokenStream = analyzer.TokenStream("", new StringReader("喝奶只喝纯牛奶,这是不可能的——黑夜中的萤火虫"));
Token token = null;
while ((token = tokenStream.Next()) != null) // 只要还有词,就不返回null
{
string word = token.TermText(); // token.TermText() 取得当前分词
Console.Write(word + " | ");
}
}

二元分词法

3.盘古分词法

再引用以下两个配置文件

/// <summary>
/// 盘古分词法
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button3_Click(object sender, EventArgs e)
{
Analyzer analyzer = new PanGuAnalyzer(); // 盘古分词
TokenStream tokenStream = analyzer.TokenStream("", new StringReader("喝奶只喝纯牛奶,这是不可能的——黑夜中的萤火虫"));
Token token = null;
while ((token = tokenStream.Next()) != null) // 只要还有词,就不返回null
{
string word = token.TermText(); // token.TermText() 取得当前分词
Console.Write(word + " | ");
}
}

盘古分词法

如果不去更改,盘古词包中并不包含所需词汇,以下是运行效果图

而用‘DictManage.exe‘来打开项目中的Dict.dct文件,添加词汇,并加以保存。

下图是修改后的运行效果:

4.中文分词算法 

 private void button1_Click(object sender, EventArgs e)
{
StringBuilder sb = new StringBuilder();
sb.Remove(, sb.Length);
string t1 = "";
int i = ;
Analyzer analyzer = new Lucene.China.ChineseAnalyzer();
StringReader sr = new StringReader(richTextBox1.Text);
TokenStream stream = analyzer.TokenStream(null, sr); long begin = System.DateTime.Now.Ticks;
Token t = stream.Next();
while (t != null)
{
t1 = t.ToString(); //显示格式: (关键词,0,2) ,需要处理
t1 = t1.Replace("(", "");
char[] separator = { ',' };
t1 = t1.Split(separator)[]; sb.Append(i + ":" + t1 + "\r\n");
t = stream.Next();
i++;
}
richTextBox2.Text = sb.ToString();
long end = System.DateTime.Now.Ticks; //100毫微秒
int time = (int)((end - begin) / ); //ms richTextBox2.Text += "耗时" + (time) + "ms \r\n=================================\r\n";
}

中文分词测试后台代码

5.简单搜索

创建web窗体SearchWords.aspx,如下图

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="SearchWords.aspx.cs" Inherits="PanGu_Search.Views.SearchWords" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>最简单的搜索引擎</title>
<script>
$(document).keydown(function (event) {
if (event.keyCode == ) {
$("#btnGetSearchResult").click();
}
});
</script>
</head>
<body>
<form id="mainForm" runat="server">
<div align="center">
<asp:Button ID="btnCreateIndex" runat="server" Text="Create Index" OnClick="btnCreateIndex_Click" />
<asp:Label ID="lblIndexStatus" runat="server" Visible="false" />
<hr />
<asp:TextBox ID="txtKeyWords" runat="server" Text="" Width=""></asp:TextBox>
<asp:Button ID="btnGetSearchResult" runat="server" Text="Search" OnClick="btnGetSearchResult_Click" />
<hr />
</div>
<div>
<ul>
<asp:Repeater ID="rptSearchResult" runat="server">
<ItemTemplate>
<li>Id:<%#Eval("Id") %><br /><%#Eval("Msg") %></li>
</ItemTemplate>
</asp:Repeater>
</ul>
</div>
</form>
</body>
</html>

前台aspx设计

  /// <summary>
/// 创建索引方法
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void btnCreateIndex_Click(object sender, EventArgs e)
{
string indexPath = Context.Server.MapPath("~/Index"); // 索引文档保存位置
FSDirectory directory = FSDirectory.Open(new DirectoryInfo(indexPath), new NativeFSLockFactory());
bool isUpdate = IndexReader.IndexExists(directory); //判断索引库是否存在
if (isUpdate)
{
// 如果索引目录被锁定(比如索引过程中程序异常退出),则首先解锁
// Lucene.Net在写索引库之前会自动加锁,在close的时候会自动解锁
// 不能多线程执行,只能处理意外被永远锁定的情况
if (IndexWriter.IsLocked(directory))
{
IndexWriter.Unlock(directory); //unlock:强制解锁,待优化
}
}
// 创建向索引库写操作对象 IndexWriter(索引目录,指定使用盘古分词进行切词,最大写入长度限制)
// 补充:使用IndexWriter打开directory时会自动对索引库文件上锁
IndexWriter writer = new IndexWriter(directory, new PanGuAnalyzer(), !isUpdate,
IndexWriter.MaxFieldLength.UNLIMITED); for (int i = ; i < ; i++)
{
string txt = File.ReadAllText(Context.Server.MapPath("~/Upload/Articles/") + i + ".txt");
// 一条Document相当于一条记录
Document document = new Document();
// 每个Document可以有自己的属性(字段),所有字段名都是自定义的,值都是string类型
// Field.Store.YES不仅要对文章进行分词记录,也要保存原文,就不用去数据库里查一次了
document.Add(new Field("id", i.ToString(), Field.Store.YES, Field.Index.NOT_ANALYZED));
// 需要进行全文检索的字段加 Field.Index. ANALYZED
// Field.Index.ANALYZED:指定文章内容按照分词后结果保存,否则无法实现后续的模糊查询
// WITH_POSITIONS_OFFSETS:指示不仅保存分割后的词,还保存词之间的距离
document.Add(new Field("msg", txt, Field.Store.YES, Field.Index.ANALYZED,
Field.TermVector.WITH_POSITIONS_OFFSETS));
// 防止重复索引,如果不存在则删除0条
writer.DeleteDocuments(new Term("id", i.ToString()));// 防止已存在的数据 => delete from t where id=i
// 把文档写入索引库
writer.AddDocument(document);
Console.WriteLine("索引{0}创建完毕", i.ToString());
} writer.Close(); // Close后自动对索引库文件解锁
directory.Close(); // 不要忘了Close,否则索引结果搜不到 lblIndexStatus.Text = "索引文件创建成功!";
lblIndexStatus.Visible = true;
btnCreateIndex.Enabled = false;
}

创建索引方法

/// <summary>
/// 搜索方法
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void btnGetSearchResult_Click(object sender, EventArgs e)
{
string keyword = txtKeyWords.Text; string indexPath = Context.Server.MapPath("~/Index"); // 索引文档保存位置
FSDirectory directory = FSDirectory.Open(new DirectoryInfo(indexPath), new NoLockFactory());
IndexReader reader = IndexReader.Open(directory, true);
IndexSearcher searcher = new IndexSearcher(reader);
// 查询条件
PhraseQuery query = new PhraseQuery();
// 等同于 where contains("msg",kw)
query.Add(new Term("msg", keyword));
// 两个词的距离大于100(经验值)就不放入搜索结果,因为距离太远相关度就不高了
query.SetSlop();
// TopScoreDocCollector:盛放查询结果的容器
TopScoreDocCollector collector = TopScoreDocCollector.create(, true);
// 使用query这个查询条件进行搜索,搜索结果放入collector
searcher.Search(query, null, collector);
// 从查询结果中取出第m条到第n条的数据
// collector.GetTotalHits()表示总的结果条数
ScoreDoc[] docs = collector.TopDocs(, collector.GetTotalHits()).scoreDocs;
// 遍历查询结果
IList<SearchResult> resultList = new List<SearchResult>();
for (int i = ; i < docs.Length; i++)
{
// 拿到文档的id,因为Document可能非常占内存(DataSet和DataReader的区别)
int docId = docs[i].doc;
// 所以查询结果中只有id,具体内容需要二次查询
// 根据id查询内容:放进去的是Document,查出来的还是Document
Document doc = searcher.Doc(docId);
SearchResult result = new SearchResult();
result.Id = Convert.ToInt32(doc.Get("id"));
result.Msg = HighlightHelper.HighLight(keyword, doc.Get("msg")); resultList.Add(result);
} // 绑定到Repeater
rptSearchResult.DataSource = resultList;
rptSearchResult.DataBind();
}

搜索方法

 protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
// 检查是否已存在生成的索引文件
CheckIndexData();
}
} /// <summary>
/// 检查索引是否创建成功
/// </summary>
private void CheckIndexData()
{
string indexPath = Context.Server.MapPath("~/Index"); // 索引文档保存位置
var files = System.IO.Directory.GetFiles(indexPath);
if (files.Length > )
{
btnCreateIndex.Visible = false;
lblIndexStatus.Text = "简单搜索";
lblIndexStatus.Visible = true;
}
}

检查索引是否存在方法

运行效果如图:

盘古分词+一元/二元分词Lucene的更多相关文章

  1. 让盘古分词支持最新的Lucene.Net 3.0.3

    原文:让盘古分词支持最新的Lucene.Net 3.0.3 好多年没升级过的Lucene.Net最近居然升级了,到了3.0.3后接口发生了很大变化,原来好多分词库都不能用了,所以上次我把MMSeg给修 ...

  2. ElasticSearch已经配置好ik分词和mmseg分词(转)

    ElasticSearch是一个基于Lucene构建的开源,分布式,RESTful搜索引擎.设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便.支持通过HTTP使用JSON进行数据索引 ...

  3. ES 09 - 定制Elasticsearch的分词器 (自定义分词策略)

    目录 1 索引的分析 1.1 分析器的组成 1.2 倒排索引的核心原理-normalization 2 ES的默认分词器 3 修改分词器 4 定制分词器 4.1 向索引中添加自定义的分词器 4.2 测 ...

  4. python中文分词:结巴分词

    中文分词是中文文本处理的一个基础性工作,结巴分词利用进行中文分词.其基本实现原理有三点: 基于Trie树结构实现高效的词图扫描,生成句子中汉字所有可能成词情况所构成的有向无环图(DAG) 采用了动态规 ...

  5. .添加索引和类型,同时设定edgengram分词和charsplit分词

    1.添加索引和类型,同时设定edgengram分词和charsplit分词 curl -XPUT 'http://127.0.0.1:9200/userindex/' -d '{   "se ...

  6. 为Elasticsearch添加中文分词,对比分词器效果

    http://keenwon.com/1404.html Elasticsearch中,内置了很多分词器(analyzers),例如standard (标准分词器).english(英文分词)和chi ...

  7. Elasticsearch拼音分词和IK分词的安装及使用

    一.Es插件配置及下载 1.IK分词器的下载安装 关于IK分词器的介绍不再多少,一言以蔽之,IK分词是目前使用非常广泛分词效果比较好的中文分词器.做ES开发的,中文分词十有八九使用的都是IK分词器. ...

  8. 和我一起打造个简单搜索之IK分词以及拼音分词

    elasticsearch 官方默认的分词插件,对中文分词效果不理想,它是把中文词语分成了一个一个的汉字.所以我们引入 es 插件 es-ik.同时为了提升用户体验,引入 es-pinyin 插件.本 ...

  9. python 中文分词:结巴分词

    中文分词是中文文本处理的一个基础性工作,结巴分词利用进行中文分词.其基本实现原理有三点: 基于Trie树结构实现高效的词图扫描,生成句子中汉字所有可能成词情况所构成的有向无环图(DAG) 采用了动态规 ...

随机推荐

  1. python学习——urlparse模块

    urlparse模块: 1.urlparse() 具体程序及结果如下: >>> url = 'http://i.cnblogs.com/EditPosts.aspx?opt=1'&g ...

  2. pymysql基本的使用方法

    1.导入模块+创建连接 import pymysql # 1.通过python去连接数据库 conn = pymysql.connect(host="127.0.0.1",port ...

  3. TextView UI美化-------自适应字体控件

    http://www.cnblogs.com/psuwgipgf/p/4874158.html 一. TextView字体随大小变化自适应TextView 实现依靠于第三方类库 第三方类来源: htt ...

  4. struts框架问题四之获取到值栈的对象

    4. 问题四 : 如何获得值栈对象 * 获得值栈对象 有三种方法 * ValueStack vs1 = (ValueStack) ServletActionContext.getRequest().g ...

  5. css布局---各种居中

    居中是我们使用css来布局时常遇到的情况.使用css来进行居中时,有时一个属性就能搞定,有时则需要一定的技巧才能兼容到所有浏览器,本文就居中的一些常用方法做个简单的介绍. 注:本文所讲方法除了特别说明 ...

  6. Netty系列(四)TCP拆包和粘包

    Netty系列(四)TCP拆包和粘包 一.拆包和粘包问题 (1) 一个小的Socket Buffer问题 在基于流的传输里比如 TCP/IP,接收到的数据会先被存储到一个 socket 接收缓冲里.不 ...

  7. Eclipse使用。

    1. 如何把项目部署到jetty根目录. 先部署.然后在jetty安装根目录下找到contexts,在里面找到你项目名.xml文件.打开后,把<Set name="configurat ...

  8. 冒泡排序java语言实现

    class bubbleSort { public static void main(String[] args){ int[] a={49,38,65,97,76,13,27,49,78,34,12 ...

  9. Django入门与实践-第16章:用户登录(完结)

    # myproject/settings.py LOGIN_REDIRECT_URL = 'home' EMAIL_BACKEND = 'django.core.mail.backends.conso ...

  10. [docker]mesos集群的启动脚本

    宿主机的IP地址列表 mesos-lb:192.168.253.159 mesos-marathon:192.168.253.159 mesos-master:192.168.253.159 meso ...