一步步开发自己的博客 .NET版(5、Lucenne.Net 和 必应站内搜索)
前言?
? ? 這次開(kāi)發(fā)的博客主要功能或特點(diǎn):
? ? 第一:可以兼容各終端,特別是手機(jī)端。
? ? 第二:到時(shí)會(huì)用到大量html5,炫啊。
? ? 第三:導(dǎo)入博客園的精華文章,并做分類(lèi)。(不要封我)
? ? 第四:做個(gè)插件,任何網(wǎng)站上的技術(shù)文章都可以轉(zhuǎn)發(fā)收藏 到本博客。
所以打算寫(xiě)個(gè)系類(lèi):《一步步搭建自己的博客》
- 一步步開(kāi)發(fā)自己的博客 ?.NET版(1、頁(yè)面布局、blog遷移、數(shù)據(jù)加載)
- 一步步開(kāi)發(fā)自己的博客 ?.NET版(2、評(píng)論功能)
- 一步步開(kāi)發(fā)自己的博客 ?.NET版(3、注冊(cè)登錄功能)
- 一步步開(kāi)發(fā)自己的博客 ?.NET版(4、文章發(fā)布功能)
- 一步步開(kāi)發(fā)自己的博客 ?.NET版(5、搜索功能)
- 一步步開(kāi)發(fā)自己的博客 ?.NET版(6、手機(jī)端的兼容)
?
演示地址:http://haojima.net/??? ? 群內(nèi)共享源碼:469075305?
?
今天來(lái)分析下 嗨-博客 中的搜索功能。搜索功能在個(gè)人網(wǎng)站里面要有這么個(gè)東西,但又不是特別重要。所以我們需要有,可以不用太深入了解,畢竟我們不是專(zhuān)門(mén)做搜索這塊的。
所以,我打算把搜索分兩塊。一塊是,用Lucene.Net實(shí)現(xiàn)站內(nèi)搜索。一塊是利用第三方搜索引擎來(lái) 實(shí)現(xiàn)站內(nèi)搜索。
?
Lucene.Net簡(jiǎn)介
Lucene.net是Lucene的.net移植版本,是一個(gè)開(kāi)源的全文檢索引擎開(kāi)發(fā)包,即它不是一個(gè)完整的全文檢索引擎,而是一個(gè)全文檢索引擎的架構(gòu),提供了完整的查詢引擎和索引引擎。開(kāi)發(fā)人員可以基于Lucene.net實(shí)現(xiàn)全文檢索的功能。 Lucene.net是Apache軟件基金會(huì)贊助的開(kāi)源項(xiàng)目,基于Apache License協(xié)議。 Lucene.net并不是一個(gè)爬行搜索引擎,也不會(huì)自動(dòng)地索引內(nèi)容。我們得先將要索引的文檔中的文本抽取出來(lái),然后再將其加到Lucene.net索引中。標(biāo)準(zhǔn)的步驟是先初始化一個(gè)Analyzer、打開(kāi)一個(gè)IndexWriter、然后再將文檔一個(gè)接一個(gè)地加進(jìn)去。一旦完成這些步驟,索引就可以在關(guān)閉前得到優(yōu)化,同時(shí)所做的改變也會(huì)生效。這個(gè)過(guò)程可能比開(kāi)發(fā)者習(xí)慣的方式更加手工化一些,但卻在數(shù)據(jù)的索引上給予你更多的靈活性,而且其效率也很高。(來(lái)源百度百科)Lucene幫助類(lèi)
其實(shí) 在之前 我也是接觸到過(guò)Lucene.net,那也是自己 做的個(gè)小玩意(博客備份小工具3) ?瞎折騰的。但是 這次打算遷移到這個(gè)系統(tǒng)中,不知怎么的 報(bào)錯(cuò)了??赡苁沁@次用的是 .net 4.5。Lucene這東西太高深,我也沒(méi)打算深究。于是 在網(wǎng)上收索了一把,資料還挺多的?!秎ucene.net 3.0.3、結(jié)合盤(pán)古分詞進(jìn)行搜索的小例子(分頁(yè)功能)》 我隨意看了下,這里有個(gè) 幫助類(lèi) 挺不錯(cuò)的,也還符合 我這樣想要的效果。這里來(lái)分析下這個(gè)幫助類(lèi)。?
1.首先創(chuàng)建索引。? ? ??
IndexWriter writer = new IndexWriter(directory_luce, analyzer, false, IndexWriter.MaxFieldLength.LIMITED); Document doc = new Document(); doc.Add(new Field(name, value, Field.Store.YES, Field.Index.NOT_ANALYZED)); writer.AddDocument(doc);這里的?
directory_luce 是索引創(chuàng)建路徑
analyzer?分析器
value 是對(duì)應(yīng) 存入索引額名字和值
2.從索引里面搜索? ? ? ?
string[] fileds = { "title", "content" };//查詢字段 QueryParser parser = null;parser = new MultiFieldQueryParser(version, fileds, analyzer);//多個(gè)字段查詢Query query = parser.Parse(keyword);int n = 1000;IndexSearcher searcher = new IndexSearcher(directory_luce, true);//true-表示只讀TopDocs docs = searcher.Search(query, (Filter)null, n);if (docs == null || docs.TotalHits == 0){return null;}else{List<SearchResult> list = new List<SearchResult>();int counter = 1;foreach (ScoreDoc sd in docs.ScoreDocs)//遍歷搜索到的結(jié)果 {try{Document doc = searcher.Doc(sd.Doc);int id = int.Parse(doc.Get("id"));string title = doc.Get("title");string content = doc.Get("content");string blogTag = doc.Get("blogTag");string url = doc.Get("url");int flag = int.Parse(doc.Get("flag"));int clickQuantity = int.Parse(doc.Get("clickQuantity"));string createdate = doc.Get("createdate");PanGu.HighLight.SimpleHTMLFormatter simpleHTMLFormatter = new PanGu.HighLight.SimpleHTMLFormatter("<font color=\"red\">", "</font>");PanGu.HighLight.Highlighter highlighter = new PanGu.HighLight.Highlighter(simpleHTMLFormatter, new PanGu.Segment());highlighter.FragmentSize = 50;content = highlighter.GetBestFragment(keyword, content);string titlehighlight = highlighter.GetBestFragment(keyword, title);if (titlehighlight != "") title = titlehighlight;list.Add(new SearchResult(title, content, url, blogTag, id, clickQuantity, flag));}catch (Exception ex){Console.WriteLine(ex.Message);}counter++;}return list;3.完整代碼
public class PanGuLuceneHelper{private PanGuLuceneHelper() { }#region 單一實(shí)例private static PanGuLuceneHelper _instance = null;/// <summary>/// 單一實(shí)例/// </summary>public static PanGuLuceneHelper instance{get{if (_instance == null) _instance = new PanGuLuceneHelper();return _instance;}}#endregion#region 00一些屬性和參數(shù)#region Lucene.Net的目錄-參數(shù)private Lucene.Net.Store.Directory _directory_luce = null;/// <summary>/// Lucene.Net的目錄-參數(shù)/// </summary>public Lucene.Net.Store.Directory directory_luce{get{if (_directory_luce == null) _directory_luce = Lucene.Net.Store.FSDirectory.Open(directory);return _directory_luce;}}#endregion#region 索引在硬盤(pán)上的目錄private System.IO.DirectoryInfo _directory = null;/// <summary>/// 索引在硬盤(pán)上的目錄/// </summary>public System.IO.DirectoryInfo directory{get{if (_directory == null){string dirPath = AppDomain.CurrentDomain.BaseDirectory + "SearchIndex";if (System.IO.Directory.Exists(dirPath) == false) _directory = System.IO.Directory.CreateDirectory(dirPath);else _directory = new System.IO.DirectoryInfo(dirPath);}return _directory;}}#endregion#region 分析器private Analyzer _analyzer = null;/// <summary>/// 分析器/// </summary>public Analyzer analyzer{get{{_analyzer = new Lucene.Net.Analysis.PanGu.PanGuAnalyzer();// }return _analyzer;}}#endregion#region 版本號(hào)枚舉類(lèi)private static Lucene.Net.Util.Version _version = Lucene.Net.Util.Version.LUCENE_30;/// <summary>/// 版本號(hào)枚舉類(lèi)/// </summary>public Lucene.Net.Util.Version version{get{return _version;}}#endregion#endregion#region 01創(chuàng)建索引/// <summary>/// 創(chuàng)建索引(先刪 后更新)/// </summary>/// <param name="datalist"></param>/// <returns></returns>public bool CreateIndex(List<SearchResult> datalist){IndexWriter writer = null;try{writer = new IndexWriter(directory_luce, analyzer, false, IndexWriter.MaxFieldLength.LIMITED);//false表示追加(true表示刪除之前的重新寫(xiě)入) }catch{writer = new IndexWriter(directory_luce, analyzer, true, IndexWriter.MaxFieldLength.LIMITED);//false表示追加(true表示刪除之前的重新寫(xiě)入) }foreach (SearchResult data in datalist){writer.DeleteDocuments(new Term("id", data.id.ToString()));//新增前 刪除 不然會(huì)有重復(fù)數(shù)據(jù) CreateIndex(writer, data);}writer.Optimize();writer.Dispose();return true;}public bool CreateIndex(SearchResult data){List<SearchResult> datalist = new List<SearchResult>();datalist.Add(data);return CreateIndex(datalist);} public bool CreateIndex(IndexWriter writer, SearchResult data){try{if (data == null) return false;Document doc = new Document();Type type = data.GetType();//assembly.GetType("Reflect_test.PurchaseOrderHeadManageModel", true, true); //命名空間名稱(chēng) + 類(lèi)名 //創(chuàng)建類(lèi)的實(shí)例 //object obj = Activator.CreateInstance(type, true); //獲取公共屬性 PropertyInfo[] Propertys = type.GetProperties();for (int i = 0; i < Propertys.Length; i++){//Propertys[i].SetValue(Propertys[i], i, null); //設(shè)置值PropertyInfo pi = Propertys[i];string name = pi.Name;object objval = pi.GetValue(data, null);string value = objval == null ? "" : objval.ToString(); //值 if (name == "id" || name == "flag")//id在寫(xiě)入索引時(shí)必是不分詞,否則是模糊搜索和刪除,會(huì)出現(xiàn)混亂 {doc.Add(new Field(name, value, Field.Store.YES, Field.Index.NOT_ANALYZED));//id不分詞 }else{doc.Add(new Field(name, value, Field.Store.YES, Field.Index.ANALYZED));}}writer.AddDocument(doc);}catch (System.IO.FileNotFoundException fnfe){throw fnfe;}return true;}#endregion#region 02在title和content字段中查詢數(shù)據(jù)/// <summary>/// 在title和content字段中查詢數(shù)據(jù)/// </summary>/// <param name="keyword"></param>/// <returns></returns>public List<SearchResult> Search(string keyword){string[] fileds = { "title", "content" };//查詢字段 QueryParser parser = null;parser = new MultiFieldQueryParser(version, fileds, analyzer);//多個(gè)字段查詢Query query = parser.Parse(keyword);int n = 1000;IndexSearcher searcher = new IndexSearcher(directory_luce, true);//true-表示只讀TopDocs docs = searcher.Search(query, (Filter)null, n);if (docs == null || docs.TotalHits == 0){return null;}else{List<SearchResult> list = new List<SearchResult>();int counter = 1;foreach (ScoreDoc sd in docs.ScoreDocs)//遍歷搜索到的結(jié)果 {try{Document doc = searcher.Doc(sd.Doc);int id = int.Parse(doc.Get("id"));string title = doc.Get("title");string content = doc.Get("content");string blogTag = doc.Get("blogTag");string url = doc.Get("url");int flag = int.Parse(doc.Get("flag"));int clickQuantity = int.Parse(doc.Get("clickQuantity"));string createdate = doc.Get("createdate");PanGu.HighLight.SimpleHTMLFormatter simpleHTMLFormatter = new PanGu.HighLight.SimpleHTMLFormatter("<font color=\"red\">", "</font>");PanGu.HighLight.Highlighter highlighter = new PanGu.HighLight.Highlighter(simpleHTMLFormatter, new PanGu.Segment());highlighter.FragmentSize = 50;content = highlighter.GetBestFragment(keyword, content);string titlehighlight = highlighter.GetBestFragment(keyword, title);if (titlehighlight != "") title = titlehighlight;list.Add(new SearchResult(title, content, url, blogTag, id, clickQuantity, flag));}catch (Exception ex){Console.WriteLine(ex.Message);}counter++;}return list;}//st.Stop();//Response.Write("查詢時(shí)間:" + st.ElapsedMilliseconds + " 毫秒<br/>"); }#endregion#region 03在不同的分類(lèi)下再根據(jù)title和content字段中查詢數(shù)據(jù)(分頁(yè))/// <summary>/// 在不同的類(lèi)型下再根據(jù)title和content字段中查詢數(shù)據(jù)(分頁(yè))/// </summary>/// <param name="_flag">分類(lèi),傳空值查詢?nèi)?/span></param>/// <param name="keyword"></param>/// <param name="PageIndex"></param>/// <param name="PageSize"></param>/// <param name="TotalCount"></param>/// <returns></returns>public List<SearchResult> Search(string _flag, string keyword, int PageIndex, int PageSize){if (PageIndex < 1) PageIndex = 1;Stopwatch st = Stopwatch.StartNew();st.Start();BooleanQuery bq = new BooleanQuery();if (_flag != ""){QueryParser qpflag = new QueryParser(version, "flag", analyzer);Query qflag = qpflag.Parse(_flag);bq.Add(qflag, Occur.MUST);//與運(yùn)算 }if (keyword != ""){string[] fileds = { "blogTag", "title", "content" };//查詢字段QueryParser parser = null;// new QueryParser(version, field, analyzer);//一個(gè)字段查詢parser = new MultiFieldQueryParser(version, fileds, analyzer);//多個(gè)字段查詢Query queryKeyword = parser.Parse(keyword);bq.Add(queryKeyword, Occur.MUST);//與運(yùn)算 }TopScoreDocCollector collector = TopScoreDocCollector.Create(PageIndex * PageSize, false);IndexSearcher searcher = new IndexSearcher(directory_luce, true);//true-表示只讀 searcher.Search(bq, collector);if (collector == null || collector.TotalHits == 0){//TotalCount = 0;return null;}else{int start = PageSize * (PageIndex - 1);//結(jié)束數(shù)int limit = PageSize;ScoreDoc[] hits = collector.TopDocs(start, limit).ScoreDocs;List<SearchResult> list = new List<SearchResult>();int counter = 1;//TotalCount = collector.TotalHits; st.Stop();//st.ElapsedMilliseconds;//毫秒foreach (ScoreDoc sd in hits)//遍歷搜索到的結(jié)果 {try{Document doc = searcher.Doc(sd.Doc);int id = int.Parse(doc.Get("id"));string title = doc.Get("title");string content = doc.Get("content");string blogTag = doc.Get("blogTag");string url = doc.Get("url");int flag = int.Parse(doc.Get("flag"));int clickQuantity = int.Parse(doc.Get("clickQuantity"));content = Highlight(keyword, content);//string titlehighlight = Highlight(keyword, title);//if (titlehighlight != "") title = titlehighlight;list.Add(new SearchResult(title, content, url, blogTag, id, clickQuantity, flag));}catch (Exception ex){Console.WriteLine(ex.Message);}counter++;}return list;}}#endregion#region 把content按照keywords進(jìn)行高亮/// <summary>/// 把content按照keywords進(jìn)行高亮/// </summary>/// <param name="keywords"></param>/// <param name="content"></param>/// <returns></returns>private static string Highlight(string keywords, string content){SimpleHTMLFormatter simpleHTMLFormatter = new PanGu.HighLight.SimpleHTMLFormatter("<strong>", "</strong>");Highlighter highlighter = new PanGu.HighLight.Highlighter(simpleHTMLFormatter, new Segment());highlighter.FragmentSize = 200;return highlighter.GetBestFragment(keywords, content);}#endregion#region 04刪除索引#region 刪除索引數(shù)據(jù)(根據(jù)id)/// <summary>/// 刪除索引數(shù)據(jù)(根據(jù)id)/// </summary>/// <param name="id"></param>/// <returns></returns>public bool Delete(string id){bool IsSuccess = false;Term term = new Term("id", id);IndexWriter writer = new IndexWriter(directory_luce, analyzer, false, IndexWriter.MaxFieldLength.LIMITED);writer.DeleteDocuments(term); // writer.DeleteDocuments(term)或者writer.DeleteDocuments(query); writer.Commit();IsSuccess = writer.HasDeletions();writer.Dispose();return IsSuccess;}#endregion#region 刪除全部索引數(shù)據(jù)/// <summary>/// 刪除全部索引數(shù)據(jù)/// </summary>/// <returns></returns>public bool DeleteAll(){bool IsSuccess = true;try{IndexWriter writer = new IndexWriter(directory_luce, analyzer, false, IndexWriter.MaxFieldLength.LIMITED);writer.DeleteAll();writer.Commit();IsSuccess = writer.HasDeletions();writer.Dispose();}catch{IsSuccess = false;}return IsSuccess;}#endregion#endregion#region 分詞測(cè)試/// <summary>/// 分詞測(cè)試/// </summary>/// <param name="keyword"></param>/// <returns></returns>public string Token(string keyword){string ret = "";System.IO.StringReader reader = new System.IO.StringReader(keyword);Lucene.Net.Analysis.TokenStream ts = analyzer.TokenStream(keyword, reader);bool hasNext = ts.IncrementToken();Lucene.Net.Analysis.Tokenattributes.ITermAttribute ita;while (hasNext){ita = ts.GetAttribute<Lucene.Net.Analysis.Tokenattributes.ITermAttribute>();ret += ita.Term + "|";hasNext = ts.IncrementToken();}ts.CloneAttributes();reader.Close();analyzer.Close();return ret;}#endregion} View Code public class SearchResult{public SearchResult() { }public SearchResult(string title, string content, string url, string blogTag, int id, int clickQuantity, int flag){this.blogTag = blogTag;this.clickQuantity = clickQuantity;this.content = content;this.id = id;this.url = url;this.title = title;this.flag = flag;}/// <summary>/// 標(biāo)題/// </summary>public string title { get; set; }/// <summary>/// 正文內(nèi)容/// </summary>public string content { get; set; }/// <summary>/// url地址/// </summary>public string url { get; set; }/// <summary>/// tag標(biāo)簽/// </summary>public string blogTag { get; set; }/// <summary>/// 唯一id/// </summary>public int id { get; set; }/// <summary>/// 點(diǎn)擊量/// </summary>public int clickQuantity { get; set; }/// <summary>/// 標(biāo)記(用戶) /// </summary>public int flag { get; set; }} View Code必應(yīng)站內(nèi)搜索
1.為什么要用必應(yīng)搜索?
因?yàn)槲覀儸F(xiàn)在做的主要功能是博客系統(tǒng),搜索只是其中的一小塊環(huán)節(jié)。而 我對(duì)這搜索并不了解,所以就用第三方搜索,省事嘛。
2.為什么不用別的三方收索呢?
百度?不用說(shuō)了,咱們程序員都懂的。谷歌?我倒是想用,可生在天朝,也是沒(méi)得辦法。選來(lái)選去 還是選了必應(yīng)。
3.怎么來(lái)使用第三方的站內(nèi)搜索?
格式如下:http://cn.bing.com/search?q=關(guān)鍵字+site:網(wǎng)站地址?
例如:http://cn.bing.com/search?q=博客+site:blog.haojima.net?
效果圖:
嘿嘿,如此之簡(jiǎn)單。既然都已經(jīng)看到效果了,那么 我們可以干些什么呢??我打算 直接把結(jié)果 顯示在我的 站內(nèi)搜索結(jié)果。為什么 不直接跳轉(zhuǎn)到這個(gè)頁(yè)面顯示 搜索結(jié)果?因?yàn)?這個(gè)頁(yè)面有廣告什么的,不能按照我自己的方式顯示。我直接把結(jié)果放我的搜索頁(yè)面 可以和 我上面用Lucene.net的搜索結(jié)果一起顯示,這樣豈不是 顯得更專(zhuān)業(yè)。,不知道的 還以為 是我自己怎么弄出來(lái)的。那么 我們?cè)趺唇馕?搜到的結(jié)果呢?我這里推薦下 ?Jumony ?之前我一直是用?HtmlAgilityPack ?,現(xiàn)在為什么不用了,因?yàn)橛辛烁玫?。HtmlAgilityPack 缺點(diǎn)是 要去xpath,然 如果頁(yè)面存在js動(dòng)態(tài)改變文檔結(jié)構(gòu)的話,我們直接F12 復(fù)制出來(lái)的 xpath是不準(zhǔn)的。那么有人 會(huì)說(shuō) ?HtmlAgilityPack ?我已經(jīng)用習(xí)慣了,不想 重新學(xué)習(xí)Jumony 。這里我告訴你錯(cuò)了,根本就需要重新學(xué)習(xí),如果你會(huì)jquery 的話。常用功能語(yǔ)法基本一樣,還支持拉姆達(dá)表達(dá)式,爽的一逼。
我們來(lái)看看 怎么使用Jumony 解析 解鎖結(jié)果吧。
var document = jumony.LoadDocument(url); var list = document.Find("#b_results .b_algo").ToList().Select(t => t.ToString()).ToList();?
兩行代碼搞定,還直接轉(zhuǎn)成了list集合。在頁(yè)面循環(huán)加載就ok了。
站內(nèi)下的某個(gè)用戶內(nèi)搜索
?我個(gè)人覺(jué)得 這是個(gè)蠻實(shí)用的功能,我們有時(shí)候 寫(xiě)了博客(很多時(shí)候我們寫(xiě)博客就是把自己怕會(huì)忘記的知識(shí)點(diǎn) 整理記錄),而后期找不到。那么通過(guò)這個(gè)功能 可以很好的解決我們的問(wèn)題。我們不想全站搜索,只搜索自己的內(nèi)容就可以了。
頁(yè)面還是用全站的搜索頁(yè)面,我們直接在搜索關(guān)鍵詞上做手腳就可以了。比如,我們想搜索 ?zhaopei ?用戶下的內(nèi)容,那么我們可以要搜索的關(guān)鍵字前面加上??blog:zhaopei?? 那么完整的搜索關(guān)鍵字就成了??blog:zhaopei 關(guān)鍵字?
?那么 ?我們要做的就是 在用戶頁(yè)面 搜索 就在關(guān)鍵字 前面加上??blog:用戶名? 我們?cè)谒阉?頁(yè)面解析的時(shí)候 需要做的就是 分解關(guān)鍵字?blog:用戶名 關(guān)鍵字? 先用空格 分割 然后如果中間有 空格的話 ,然后判斷 前面五個(gè)字符是不是?blog:?然后截取 到用戶名和 關(guān)鍵字。
我們下面具體看看 在Lucene.net 和 必應(yīng)搜索里面是怎么做的。
1.Lucene.net?
#region 加載 Lucene.net 的搜索結(jié)果/// <summary>/// 加載 Lucene.net 的搜索結(jié)果/// </summary>/// <returns></returns>public ActionResult ShowLuceneResult(){if (!Request.QueryString.AllKeys.Contains("key"))return null;string key = Request.QueryString["key"];var zhankey = key.Split(' ');//分割關(guān)鍵字var blogName = string.Empty;if (zhankey.Length >= 2){var str = zhankey[0].Trim();if (str.Length > 6 && str.Substring(0, 5) == "blog:")blogName = str.Substring(5);//取得用戶名 }string userid = Request.QueryString.AllKeys.Contains("userid") ? Request.QueryString["userid"] : "";//這里判斷是否 用戶名不為空 然后取得用戶對(duì)應(yīng)的 用戶ID (因?yàn)?我在做Lucene 是用用戶id 來(lái)標(biāo)記的)if (!string.IsNullOrEmpty(blogName)){key = key.Substring(key.IndexOf(' '));var userinfo = CacheData.GetAllUserInfo().Where(t => t.UserName == blogName).FirstOrDefault();if (null != userinfo)userid = userinfo.Id.ToString();}string pIndex = Request.QueryString.AllKeys.Contains("p") ? Request.QueryString["p"] : "";int PageIndex = 1;int.TryParse(pIndex, out PageIndex);int PageSize = 10;var searchlist = PanGuLuceneHelper.instance.Search(userid, key, PageIndex, PageSize);return PartialView(searchlist);}#endregion?2.??必應(yīng)搜索
#region 加載 bing 的搜索結(jié)果/// <summary>/// 加載 bing 的搜索結(jié)果/// </summary>/// <returns></returns>public ActionResult ShowBingResult(){if (!Request.QueryString.AllKeys.Contains("key"))return null;string key = Request.QueryString["key"];//搜索關(guān)鍵字JumonyParser jumony = new JumonyParser();//http://cn.bing.com/search?q=AJAX+site%3ablog.haojima.net&first=11&FORM=PEREstring pIndex = Request.QueryString.AllKeys.Contains("p") ? Request.QueryString["p"] : "";int PageIndex = 1;int.TryParse(pIndex, out PageIndex);PageIndex--;//如:blog:JeffreyZhao 博客var zhankey = key.Split(' ');//先用空格分割var blogName = string.Empty;if (zhankey.Length >= 2){var str = zhankey[0].Trim();if (str.Length > 6 && str.Substring(0, 5) == "blog:")blogName = "/" + str.Substring(5);//這里取得 用戶名 }if (!string.IsNullOrEmpty(blogName))key = key.Substring(key.IndexOf(' '));//如:var url = "http://cn.bing.com/search?q=" + key + "+site:" + siteUrl + blogName + "&first=" + PageIndex + "1&FORM=PERE";var document = jumony.LoadDocument(url);var list = document.Find("#b_results .b_algo").ToList().Select(t => t.ToString()).ToList();var listli = document.Find("li.b_pag nav ul li");if (PageIndex > 0 && listli.Count() == 0)return null;if (listli.Count() > 1){var text = document.Find("li.b_pag nav ul li").Last().InnerText();int npage = -1;if (text == "下一頁(yè)"){if (listli.Count() > 1){var num = listli.ToList()[listli.Count() - 2].InnerText();int.TryParse(num, out npage);}}elseint.TryParse(text, out npage);if (npage <= PageIndex)list = null;}return PartialView(list);}#endregion?看看 我們的搜索結(jié)果的效果圖吧。
總結(jié)
首先 搜索是必不可少的功能,但又不是主要功能。那么我們可以直接用lucene.net 來(lái)做搜索,然后用必應(yīng)搜索做備用。但是 用必應(yīng) 有個(gè)弊端。就是 ?如果我們 的文章頁(yè)面 被用戶自己刪除了,而 必應(yīng)已經(jīng)收錄了,那么 我們?cè)谒阉鹘Y(jié)果頁(yè)面 點(diǎn)擊 可能就是404 或 500 了。當(dāng)然 我們自己的?lucene.net 也會(huì)有這個(gè) 問(wèn)題,我們可以在用戶刪除 文章的時(shí)候 也刪除 對(duì)應(yīng)的那天搜索索引就好了。
?
演示地址:http://blog.haojima.net/Search/Index?key=blog:zhaopei 博客&p=1?
如果您對(duì)本篇文章感興趣,那就麻煩您點(diǎn)個(gè)贊,您的鼓勵(lì)將是我的動(dòng)力。?當(dāng)然您還可以加入QQ群:討論。
如果您有更好的處理方式,希望不要吝嗇賜教。
一步步開(kāi)發(fā)自己的博客 .NET版系列:http://www.cnblogs.com/zhaopei/tag/Hi-Blogs/
本文鏈接:http://www.cnblogs.com/zhaopei/p/4783986.html
總結(jié)
以上是生活随笔為你收集整理的一步步开发自己的博客 .NET版(5、Lucenne.Net 和 必应站内搜索)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Caused by: android.o
- 下一篇: Spring IoC — 基于XML的配