搜索引擎系統的原理和實踐

轉載自https://www.cnblogs.com/binyue/p/3464052.html

搜索引擎的原理和分析指標

(1)搜索引擎的工作原理

搜索引擎的工作原理大致可以分爲:
蒐集信息:搜索引擎的一個部分可以實現信息自動蒐集。
整理信息:搜索引擎通過創建索引爲抓取到的信息添加規則。
接受查詢:用戶向搜索引擎輸入關鍵詞提交查詢,系統接受用戶查詢,並且排序後並返回查詢結果。搜索引擎根據每個用戶的不同關鍵詞檢查索引庫,迅速找到用戶需要的資料,並返回給用戶。目前,搜索查詢結果主要是以含有部分摘要信息的網頁鏈接給出的,這樣利用上述鏈接,使用者可以訪問含有所需資料的站點與網頁。一般情況下,搜索引擎會提供部分摘要信息在這些鏈接下,可以幫助用戶判斷此鏈接是否含有自己需要的內容。

(2)搜索引擎的評價及分析指標
在傳統的評價體系中,衡量搜索引擎的基本指標是召回率(Recall)和準確率(Pricision)。這兩項標準一直是被廣泛承認的主要標準。準確率是搜索出的文檔數與所有的文檔數的比率;召回率爲搜索出的相關文檔數與實際相關文檔數的比值。
相關度——專人評估每個搜索引擎的前幾個結果,評價標準有是否是正態相關等,著名的指標有DCG等。
速度——就是用戶輸入搜索詞,到得到搜索結果的時間。這是李開復老師提出的評價體系,經驗告訴我們,0.2秒的速度會導致用戶滿意度的落差,降低未來重複使用的機會。
索引規模——搜索引擎會了解引擎自己的規模,通過了解爬蟲抓取到的網頁(除去重複的),通常不知道另外的搜索引擎的規模,於是我們可以根據對比兩方搜索結果的爬取,得知有多少網頁獨有的,可以推斷出搜索引擎的索引規模。
新鮮度——搜索結果的時效性,並不限於新聞內容,其他的例如促銷信息等也和時效息息相關。
穩定性——稱爲搜索服務的系統穩定性,也是所有系統主要的評判標準。
(3)搜索引擎的組成與結構
一般的,全文(文本)搜索引擎由可以細分爲三個模塊,分別是爬蟲搜索和信息處理部分、索引處理部分、檢索服務部分(用戶查詢部分):
爬蟲搜索部分主要在互聯網中通過多種搜索策略,蒐集信息,。
索引處理部分是理解編排爬蟲搜索部分所抓取到的信息,從中抽取出索引內容,生成文檔庫的索引表,同時添加摘要等。
檢索服務部分是根據用戶的查詢在索引庫中快速檢索文檔,進行相關度評價,對將要輸出的結果排序,並能按用戶的查詢需求合理反饋信息。

爬蟲搜索和信息處理部分的設計和實現

(1)網絡爬蟲設計
網絡爬蟲可以理解爲一個簡易的瀏覽器機器人。
爬蟲可以自動抓取網頁信息,按照一定的策略蒐集網頁,並且判斷與關鍵詞是否相關,這是整個系統的核心。網絡爬蟲有很多種,根據爬行策略等。最原始的是傳統爬蟲。也是最經典的,給傳統爬蟲一個或幾個網頁鏈接地址。爬蟲爬取的過程中,會不斷補充新的鏈接,獲得接下來網頁上的URL,理論上,一個爬蟲甚至可以爬取整個互聯網。除非我們設置一定的邊界條件。

(1)設計基於Java網絡編程的爬蟲;
(2)通過IO操作等,去除待爬取URL列表對應的URL的網頁代碼;
(3)提取網頁信息,本次設計使用的是傳統爬蟲。這裏要說明聚焦爬蟲和傳統爬蟲的主要區別點,聚焦爬蟲可以設計匹配算法,判斷網頁和需要的主題是否相關,避免不必要的爬取;
(4)根據一定的搜索策略,如深度搜索,設計從第一個鏈接出發,依次訪問該網頁上的所有鏈接,訪問完成後,可以設置遞歸算法訪問下一層,直到達到設定的搜索策略。

(2)提取網頁中的有效信息 
從HTML頁面提取內容所面臨的主要問題是,我們必須尋找一種方法精確地識別出自己想要的那一部分內容。
以下是利用正則表達式匹配並提取網頁中特定信息的方法:

1

2

3

4

5

正則匹配網頁中所有URL鏈接:

<a[^>]*?>[\s\S]*?</a>

獲取圖片:

<img[^>]*?/?>

<div[^>]*?id="idname"[^>]*?>[\s\S]*?</div>

(3)對蒐集的信息進行分詞
Lucene自帶了多個分詞器StandardAnalyzer,CJKAnalyzer,以及MMAnalyzer(極易中文分詞組件)等。
目前應用比較多的是MMAnalyzer,特別是Lucene較早的版本,本次設計的系統,應用的分詞組件就是極易中文分詞組件。
分詞算法的設計和理解需要較深入的數學和計算機科學知識,在這裏不做研究,只是簡單瞭解常見的分詞算法。
現有的中文分詞算法可分爲三大類,這裏我們主要研究基於字符串匹配的分詞方法。
基於字符串匹配的分詞方法最容易理解。它的實現很簡單,應用卻廣泛,我們也可以稱之爲機械分詞。機械分詞算法通過一系列的步驟,例如通過建立詞典,按照一定的策略,類似我們去查詞典的行爲。就可以將待分析的字符串與一個足夠大的機器詞典中的詞條進行匹配,一旦找到某個字符串,就會輸出匹配成功,我們可以理解爲匹配到一個合適的關鍵詞。
比如搜索“濟南大學好不好”,則返回結果會包含很多“濟南大學”,“濟南””大學”等詞語的網頁,搜索引擎如果採用正向最大匹配去判斷,就需要把“濟南大學”當做一個不可拆分的詞語來索引記錄並返回最終結果。

索引處理部分的設計和實現

(1)索引技術及搜索的實現
倒排索引不是由具體的記錄來確定屬性值,和通常的認識相反,由屬性值來確定記錄,叫做倒排索引(inverted index)。倒排文件(inverted file)就是利用倒排索引的文件。
建立倒排索引是搜索引擎的關鍵步驟。倒排索引一般表示爲一個關鍵詞,然後是它的頻度(出現的次數),位置(出現在哪個網頁中,同時包括有關的日期,所有者等信息),相當於爲互聯網的上千萬頁網頁做了一個索引,如同一本詞典的目錄。用戶想看瀏覽那一個單詞,根據目錄索引即可找到相關的頁面。
Lucene應用了倒排的思想,建立倒排文件結構,倒排的理解下面會說明。該結構及相應的生成算法如下:   
設有兩篇日誌A和B,
日誌A的內容是,“Haha,Today is sunny!”   
日誌B的內容爲,”Oh,Today is rainning!”
(1)分析日誌的關鍵詞。Lucene類似數據庫中的字段查詢,是基於關鍵詞索引和查詢的,我們必須取得數據的關鍵詞,在這裏本文簡單介紹一下分詞:   
現在有某篇日誌博文,可以理解爲一個字符串,最開始的操作是需要找出所有單詞。英文單詞比較好處理,中文的處理在下面介紹。
日誌裏的”Haha”等詞沒有什麼實際意義,這些不代表概念的詞需要過濾掉。       
在lucene中以上措施由Analyzer類完成。 經過上面處理後,
日誌1的所有關鍵詞爲:[today] [is] [sun] 。 
日誌2的所有關鍵詞爲:[tomorrow] [is] [rain]。
(2)建立倒排索引。得到關鍵詞後,我們就可以建立倒排索引了。上面的對應關係是:“日誌ID”去對應“日誌中的關鍵詞”。倒排索引後會變成: “日誌中關鍵詞”去對應“擁有該關鍵詞的所有日誌ID”。
日誌A,B經過倒排後變成:

關鍵詞

日誌ID 

today

A

tomorrow 

is

A/B 

sun

A

rain

B


定位關鍵詞在哪些日誌中還不夠,還需要了解關鍵字在日誌中出現的兩種位置,出現位置和出現次數:
1)字符位置,日誌中的出現位置;
2)關鍵詞位置,該詞是日誌中第幾個關鍵詞(詞組(phase)查詢快,節約索引空間),在這裏我們使用第二種位置。

關鍵詞

日誌ID[出現頻率]

出現位置

today 

A[1]  

1

tomorrow 

B[1]

is 

A[1]

2


lucene索引實現中比較核心的實現就是剛纔的操作。Lucene這裏放棄採用數據庫索引中經常應用的B+樹結構,按字符順序排列關鍵詞,因此我們用過二分查找(Binary Search)快速獲得關鍵詞的定位。
(3)進一步壓縮和實現。Lucene中引入了field的概念,用於表達信息所在位置,在《淘寶技術十年》一書中,淘寶最初的商品搜索架構Searcher就是採用這種類似的存儲結構,索引創建中,域的詳細信息被讀寫在詞典文件中,一個field信息對應一個關鍵詞,可以極大縮減了存儲開支。Lucene會進一步將上面三列分別作爲詞典文件(Term Dictionary)、頻率文件(frequencies)、位置文件 (positions)保存。詞典文件是Lucene中重要的數據結構,文件擁有每個關鍵字的記錄,指向其他文件的指針也可以保存。於是我們可以找到該關鍵字的位置頻率信息。
(4)建立索引後,可以很容易的使用二分查找去定位,查詢速度非常快,
而如果用普通的順序匹配算法,耗費時間將會非常大。

(2)中文分詞技術
詞語是語言學中最小的,並且能夠獨立活動的語言成分。和英語不同,中文沒有空格這一英文單詞之間的自然分界符。而漢語遠沒有那麼簡單,漢語的基本書寫單位是字,詞語和詞語之間沒有特殊的區分標記,同時,存在着大量的一次多意等。中文搜索引擎中,中文分詞是信息處理和檢索的基礎,也是關鍵。例如,英文句子“Today is fine.”,用中文則爲:“今天真好。”。對於英文句子,計算機可以很簡單通過空格區分三個單詞,但是想要理解“今天”“天真”難度就比較大。如何把中文的漢字文字序列,也就說我們平時說的話,讀的句子,處理一系列有意義的詞,稱爲中文分詞。
中文分詞技術在人工智能中,是自然語言處理技術的一種。對於一句話,比如有意思的“前門到了,請從後門下車”,我們可以在生活中區分,但是如何讓電腦像人腦一樣,讓計算機理解這個過程,這是人工智能的一個重要研究方向,就是分詞算法。
開源社區中存在着衆多中文分詞工具,如盤古分詞,庖丁中文分詞等,應用比較廣泛的是IK Analyzer。
IK Analyzer 是一個開源的中文分詞工具包。從第一版開始,IKAnalyzer推出多個大版本。起初, IK Analyzer和Luence一起,作爲主要的應用,結合中國分詞組件字典和解析算法。但是隨着進一步發展,IK Analyzer獨立出來,成爲面向全部系統的開放分詞組件,不過,和lucene結合使用最好。IK Analyzer可以在不需要標註詞性的情況下,實現較好的分詞效果。IK Analyzer可以通過配置詞典文件,進一步提升分詞效果。

(3)分詞 建立索引
下面說明常用的插件工具,CJKAnalyzer分析器的思想:
如果處理中文漢字,CJK會對讀取到的兩個字作爲一個詞條。
例如趙錢孫李,使用CJKAnalyzer分析器分詞後會得到如下詞條:
趙錢 錢孫 孫李。
進而程序會根據選定的詞典庫,進行逐個詞條的匹配,這是一項很耗時的工作,具體的過程可以參考源碼中的實現,這裏只是簡單介紹。
下面是一個CJKAnalyzer 分詞的簡單實驗。
我們輸入一段文本:“植樹節,我們來到山上,大家一起新勤勞動,每個人都很高興”。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

public class BingoAnalyzer {

public static void main(String[] args) {

   try {

    File file = new File("E:\\bingo\testbingo1.txt");

    FileReader endWords = new FileReader("E:\\bingo\testbingo2.txt");

    Reader reader = new FileReader(file);  

    Analyzer bal = new CJKAnalyzer();

    TokenStream ts = bal.tokenStream("", reader);

    Token t = null;

    int n = 0;

    while((t = ts.next()) != null ){

     n ++ ;

     System.out.println("詞條"+n+"分詞結果 :"+t.termText());

    }

    System.out.println("產生詞條"+n+" 條");

    

   catch (Exception e) {

    e.printStackTrace();

   }

}

}

  


上面的程序中只是簡單演示瞭如何分詞,輸出結果如下:
詞條1分詞結果:植樹
詞條2分詞結果:節我
詞條3分詞結果:們來
詞條4分詞結果:到山
詞條5分詞結果:上大
詞條6分詞結果:家一
詞條7分詞結果:起辛
詞條8分詞結果:勤勞
詞條9分詞結果:動每
詞條10分詞結果:個人
詞條11分詞結果:都很
詞條12分詞結果:高興
產生詞條12條。
我們可以看到,大概會產生一定數量的垃圾詞條,有些還不可用。如果使用Lucene標準分詞器StandardAnalyzer,開銷大概會減小一半。但是效率較低,而且兩者都要對重複的詞條進行一些處理。
CJKAnalyzer分析器的分詞工具是CJKTokenizer核心類。對詞條的過濾操作,CJKAnalyze通過stopTable類,在程序中指定。

(3)文檔分析及過濾
索引建立,至關重要。例如,我們需要對d:\\test\index目錄下的文件進行搜索。首先要做的是,建立索引。
在lucene中,大致可以劃分爲一下幾個操作:
(1)創建存放索引的目錄Directory
(2)創建索引器配置管理類IndexWriterConfig
(3)lucene中的索引目錄等類創建索引器
(4)利用前面創建好的索引器,採用Lucene的數據結構document寫入到文件中。

檢索服務部分的設計與實現

(1)lucene全文檢索的實現機制
Lucene的API設計的非常實用,可以理解爲一個大型的數據庫,通過存儲結構/接口這一結構,可以方便的進行查詢等操作。
索引表通過IndexWriter建立,可以理解爲數據庫中的table。Lucene通過Analyzer指定構建方式,Lucene提供了幾種環境下使用的Analyzer:SimpleAnalyzer、StandardAnalyzer、GermanAnalyzer等,其中StandardAnalyzer是經常使用的,因爲它提供了對於中文的支持。

(2)Lucene基於索引的查詢
Lucene蘊含了豐富的面向對象思想,作爲Apache通用的工具包,Lucene給那些需要將全文檢索功能添加到系統中的軟件開發人員提供了非常多的便利。
下面是學習過程中,Lucene基於索引的複合查詢代碼片段:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

//新建查詢實例

Query query=MultiFieldQueryParser.parse("索引",new String[]{"title","content"},analyzer);

        Query mquery=new WildcardQuery(new Term("sender","bluedavy*"));

 

        TermQuery tquery=new TermQuery(new Term("name","jerry"));

         

 

        BooleanQuery bquery=new BooleanQuery();

 

        bquery.add(query,true,false);

 

        bquery.add(mquery,true,false);

 

        bquery.add(tquery,true,false);

//索引查詢實例

        Searcher searcher=new IndexSearcher(indexFilePath);

 

        Hits hits=searcher.search(bquery);

 

        for (int i = 0; i < hits.length(); i++) {

 

         System.out.println(hits.doc(i).get("name"));

 

    }

  

搜索引擎開源框架的選型 

(1)Nutch
Apache Nutch是一個高度可擴展的和可伸縮的開源網絡爬蟲軟件項目,起源自Apache Lucene。項目多樣化,現在包括兩個協議的代碼庫:
Nutch 1.x:是一個成熟,生產就緒的爬蟲。1.x依賴於Apache Hadoop。
Nutch 2.x:一個新興的替代,直接的靈感來自1.x,但不同的一個關鍵:抽象存儲遠離任何特定的基礎數據存儲,採用Apache Gora處理對象持久性映射。這意味着我們可以存儲都極其靈活的模型/棧的實現(提取時間,地位,內容,解析文本,類型,反向鏈接,等等)爲多個NoSQL存儲解決方案。
Nutch 提供了運行一個搜索引擎所需的全部工具,包括Web爬蟲和全文搜索。
Nutch是基於Lucene的。Lucene爲Nutch提供了文本索引和搜索的API。
在Nutch和Lucene的選擇上,評判的標準主要是是否需要抓取數據的話,如果不需要,應該使用Lucene。
(2)Lucene
Lucene 是apache軟件基金會一個開源的索引工具包,
是一個基於Java的文本搜索引擎索引工具包,提供一個全文搜索引擎的整體架構,
以及完整的查詢和索引引擎,其中包含了部分文本處理工具。
Lucene的發展很快,致力於爲搜索研發人員貢獻了一個方便易用的組件,
使得實現全文檢索的功能更加方便,同樣,你也可以以此爲骨骼建立起一套完備的全文搜索引擎。

(3)lucene全文檢索的實現機制
Lucene的API設計的非常實用,可以理解爲一個大型的數據庫,通過存儲結構/接口這一結構,可以方便的進行查詢等操作。
索引表通過IndexWriter建立,可以理解爲數據庫中的table。Lucene通過Analyzer指定構建方式,Lucene提供了幾種環境下使用的Analyzer:SimpleAnalyzer、StandardAnalyzer、GermanAnalyzer等,其中StandardAnalyzer是經常使用的,因爲它提供了對於中文的支持。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章