盤古分詞+一元/二元分詞Lucene

来源:https://www.cnblogs.com/HDX123/archive/2018/05/10/9021388.html
-Advertisement-
Play Games

本文參考自:https://blog.csdn.net/mss359681091/article/details/52078147 本文所有需要用到的文件下載包含項目: Lucene配置文件下載 本文項目下載Zip 用vs2015創建Windows窗體應用程式,創建好項目時記得將其屬性改為“控制台應 ...


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

本文所有需要用到的文件下載包含項目:

 Lucene配置文件下載

本文項目下載Zip 

用vs2015創建Windows窗體應用程式,創建好項目時記得將其屬性改為“控制台應用程式”,當然也可以是預設的,只是這樣方便些。如下圖

1.一元分詞法

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

 1 /// <summary>
 2         /// 一元分詞法
 3         /// </summary>
 4         /// <param name="sender"></param>
 5         /// <param name="e"></param>
 6         private void button1_Click(object sender, EventArgs e)
 7         {
 8             Analyzer analyzer = new StandardAnalyzer(); // 標準分詞 → 一元分詞  
 9             TokenStream tokenStream = analyzer.TokenStream("", new StringReader("喝奶只喝純牛奶,這是不可能的——黑夜中的螢火蟲"));
10             Token token = null;
11             while ((token = tokenStream.Next()) != null) // 只要還有詞,就不返回null  
12             {
13                 string word = token.TermText(); // token.TermText() 取得當前分詞  
14                 Console.Write(word + "   |  ");
15             }
16         }
一元分詞法

 

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.簡單搜索

創建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 == 13) {
        $("#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="250"></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 = 1; i < 3; 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(100);
            // TopScoreDocCollector:盛放查詢結果的容器  
            TopScoreDocCollector collector = TopScoreDocCollector.create(1000, true);
            // 使用query這個查詢條件進行搜索,搜索結果放入collector  
            searcher.Search(query, null, collector);
            // 從查詢結果中取出第m條到第n條的數據  
            // collector.GetTotalHits()表示總的結果條數  
            ScoreDoc[] docs = collector.TopDocs(0, collector.GetTotalHits()).scoreDocs;
            // 遍歷查詢結果  
            IList<SearchResult> resultList = new List<SearchResult>();
            for (int i = 0; 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 > 0)
            {
                btnCreateIndex.Visible = false;
                lblIndexStatus.Text = "簡單搜索";
                lblIndexStatus.Visible = true;
            }
        }
檢查索引是否存在方法

 

 運行效果如圖:

 

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 很多時候都很難琢磨客戶在想什麼,也許是自己業務經驗不足,也許是客戶要顯示出他在軟體方面也非常的專業。記得以前聽過一個故事,說一個富人想娶個媳婦,然後他比較鐘意的有三個女人,然後就想從三個女人中選一個,他分別給了三個女人各一千塊錢,並對她們說,“我這裡有一個房間,請你們用自己的一千塊錢儘可能的將房間填 ...
  • //Map的四種遍歷方法 public static void main(String[] args) { Map<String, String> map = new HashMap<String, String>(); map.put("1", "value1"); map.put("2", "v ...
  • 條件語句 if語句: if 判斷語句 elif 判斷語句 else if必須要有,else可寫可不寫,elif可以不寫也可以寫多個 三目運算: a = 3 if a>5: print(True) else: print(False) a = 3 True if a > 5 else False 條件 ...
  • 1.在屏幕上輸出“你好” //Programmer name Helloword.javapublic class Helloword { public static void main(String args[]){ System.out.print("你好!!!"); }} 2. 用if-els ...
  • AspnetCore 緩存篇 一、緩存的作用 怎樣理解緩存: 其實所有的程式,架構,優化,線程...等技術手段,最終的目的都是如何使產品快速的響應用戶的操作,提高用戶的體驗性,目標都是為了系統的使用者,緩存的存在也是同樣的道理,緩存常用於存放不經常更改的數據信息,比如,用戶的基礎數據、Token等一 ...
  • 一、課程介紹 本次分享課程包含兩個部分《.NET輕量級ORM框架Dapper修煉手冊》和《.NET輕量級ORM框架Dapper葵花寶典》,阿笨將帶領大家一起領略輕量級ORM框架Dapper的魅力。 本次分享課程適合人群範圍: 一、《.NET輕量級ORM框架Dapper修煉手冊》適合人群如下: 1、我 ...
  • 第二章 簡單的c#程式 1.註釋 2.命名空間 3.類 4.Main方法 5.標識符及關鍵字 6.c#語句 7.命名規範 自拍視頻:百度雲盤:https://pan.baidu.com/s/1D-r7sdtPkZf7_B2WfN8z1Q 密碼:1xrs 課堂筆記:百度雲盤:https://pan.b ...
  • GC的前世與今生 雖然本文是以.net作為目標來講述GC,但是GC的概念並非才誕生不久。早在1958年,由鼎鼎大名的圖林獎得主John McCarthy所實現的Lisp語言就已經提供了GC的功能,這是GC的第一次出現。Lisp的程式員認為記憶體管理太重要了,所以不能由程式員自己來管理。但後來的日子里L ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...