python實現一個搜尋引擎(Pylucene)執行個體教程

來源:互聯網
上載者:User
  1. Document,文檔類。在Pylucene中建立索引的基本單位是“文檔”(Document),一個Document可能是一個網頁、一篇文章、一封郵件。Document是用以構建索引的單位同時也是進行搜尋時的結果單位,對它進行合理的設計能夠提供個人化的搜尋服務。

  2. Filed,域類。一個Document之中可以包含多個域(Field)。Filed是Document的組成部分,就如一篇文章的組成可能是文章標題、文章主體、作者、發表日期等多個Filed。

  3. 將一個頁面作為一個Document,包含三個Field分別是頁面的URL地址(url)、頁面的標題(title)、頁面的主要文字內容(content)。對於索引的儲存方式選擇使用SimpleFSDirectory類,將索引儲存至檔案之中。分析器選擇Pylucene內建的CJKAnalyzer,該分析器對中文支援較好,適用於中文內容的文本處理。

  4. 什麼是搜尋引擎?

搜尋引擎是“對網路資訊資源進行搜集整理並提供資訊查詢服務的系統,包括資訊搜集、資訊整理和使用者查詢三部分”。1是搜尋引擎的一般結構,資訊搜集模組從網路採集資訊到網路資訊庫之中(一般使用爬蟲);然後資訊整理模組對採集的資訊進行分詞、去停用詞、賦權重等操作後建立索引表(一般是倒排索引)構成索引庫;最後使用者查詢模組就可以識別使用者的檢索需求並提供檢索服務啦。

圖1 搜尋引擎的一般結構

2. 使用python實現一個簡單搜尋引擎

2.1 問題分析

從圖1看,一個完整的搜尋引擎架構從互連網搜集資訊開始,可以使用python編寫一個爬蟲,這是python的強項。

接著,資訊處理模組。分詞?停用詞?倒排表?what?什麼亂七八糟的?不用管它,我們有前輩們造好的輪子---Pylucene(lucene的python封裝版本,Lucene能夠協助開發人員為軟體、系統增添檢索功能。Lucene是一套用於全文檢索索引和搜尋的開來源程式庫)。使用Pylucene可以簡單的協助我們完成對採集到的資訊進行處理,包括索引的建立和搜尋。

最後,為了能在網頁上使用我們的搜尋引擎,我們使用flask這個輕量級 Web 應用程式架構做一個小網頁擷取搜尋語句並反饋搜尋結果。

2.2 爬蟲設計

主要搜集以下內容:目標網頁的標題、目標網頁的主要文字內容、目標網頁指向其他頁面的URL地址。網路爬蟲的工作流程2所。爬蟲的主要資料結構是隊列。首先,起始的種子節點進入隊列,然後從隊列中取出一個節點訪問,抓取該節點頁面上的目標資訊,再將該節點頁面指向其他頁面的URL連結放進隊列,再從隊列中取出新的節點進行訪問,直至隊列為空白。通過隊列“先進先出”的特點實現廣度優先的遍曆演算法,逐個訪問網站的每一頁面。

圖2

2.3 pylucene的使用

Pylucene中關於建立索引的類主要有Directory、Analyzer、IndexWriter、Document、Filed。

Directory是Pylucene中關於檔案操作的類。它有SimpleFSDirectory和RAMDirectory、CompoundFileDirectory、FileSwitchDirectory等11個子類,列舉的四個是與索引目錄的儲存相關的子類,SimpleFSDirectory是將構建的索引儲存至檔案系統之中;RAMDirectory是將索引儲存至RAM記憶體之中;CompoundFileDirectory是一種複合的索引儲存方式;而FileSwitchDirectory允許臨時切換索引的儲存方式以發揮各種索引儲存方式的優點。

Analyzer,分析器。它是對爬蟲獲得的將要進行構建索引的文本進行處理的類。包括了文本進行分詞操作、去掉停用詞、轉換大小寫等操作。Pylucene內建了若干分析器,構建索引時也可使用第三方分析器或者自寫分析器。分析器的好壞關係到構建索引的品質與搜尋服務的所能提供的精準度與速度。

IndexWriter,索引寫入類。在Directory開闢的儲存空間中IndexWriter可以進行索引的寫入、修改、增添、刪除等操作,但不可進行索引的讀取也不能搜尋索引。

Document,文檔類。在Pylucene中建立索引的基本單位是“文檔”(Document),一個Document可能是一個網頁、一篇文章、一封郵件。Document是用以構建索引的單位同時也是進行搜尋時的結果單位,對它進行合理的設計能夠提供個人化的搜尋服務。

Filed,域類。一個Document之中可以包含多個域(Field)。Filed是Document的組成部分,就如一篇文章的組成可能是文章標題、文章主體、作者、發表日期等多個Filed。

將一個頁面作為一個Document,包含三個Field分別是頁面的URL地址(url)、頁面的標題(title)、頁面的主要文字內容(content)。對於索引的儲存方式選擇使用SimpleFSDirectory類,將索引儲存至檔案之中。分析器選擇Pylucene內建的CJKAnalyzer,該分析器對中文支援較好,適用於中文內容的文本處理。

使用Pylucene構建索引的具體操作步驟如下:

lucene.initVM()INDEXIDR = self.__index_dirindexdir = SimpleFSDirectory(File(INDEXIDR))①analyzer = CJKAnalyzer(Version.LUCENE_30)②index_writer = IndexWriter(indexdir, analyzer, True, IndexWriter.MaxFieldLength(512))③document = Document()④document.add(Field("content", str(page_info["content"]), Field.Store.NOT, Field.Index.ANALYZED))⑤document.add(Field("url", visiting, Field.Store.YES, Field.Index.NOT_ANALYZED))⑥document.add(Field("title", str(page_info["title"]), Field.Store.YES, Field.Index.ANALYZED))⑦index_writer.addDocument(document)⑧index_writer.optimize()⑨index_writer.close()⑩

索引的構建有10個主要的步驟:

①執行個體化一個SimpleFSDirectory對象,將索引儲存至本地檔案之中,儲存的路徑為自訂的路徑“INDEXIDR”。

②執行個體化一個CJKAnalyzer分析器,執行個體化時的參數Version.LUCENE_30為Pylucene的版本號碼。

③執行個體化一個IndexWriter對象,所攜帶的四個參數分是前面的執行個體化的SimpleFSDirectory對象和CJKAnalyzer分析器,布爾型的變數true表示建立一個新的索引,IndexWriter.MaxFieldLength指定了一個索引最大的域(Filed)數量。

④執行個體化一個Document對象,取名為document。

⑤為document添加名稱為“content”的域。該域的內容為爬蟲擷取的某一網頁頁面的主要文字內容。該操作的參數是執行個體化並馬上使用的Field對象;Field對象的四個參數分別是:

(1)“content”,域的名稱。

(2)page_info["content"],爬蟲搜集到的網頁頁面的主要文字內容。

(3)Field.Store是用於表示該域的值是否可以恢複原始字元的變數,Field.Store.YES表示儲存在該域中的內容可以恢複至原始常值內容,Field. Store.NOT表示不可恢複。

(4)Field.Index變數表示該域的內容是否應用分析器處理,Field. Index.ANALYZED表示對該域字元處理流量分析器,Field. Index. NOT_ANALYZED則表示不對該域流量分析器處理字元。

⑥添加名稱為“url”的域用以儲存該頁面地址。

⑦添加名稱為“title”的域用以儲存該頁面的標題。

⑧執行個體化IndexWriter對像將文檔document寫入索引檔案。

⑨最佳化索引庫檔案,合并索引庫中的小檔案為大檔案。

⑩單個周期內構建索引操作完成後關閉IndexWriter對像。

Pylucene關於建立索引的搜尋的類主要有IndexSearcher、Query、QueryParser[16]。

IndexSearcher,索引搜尋類。用於在IndexWriter構建的索引庫中進行搜尋操作。

Query,描述查詢請求的類。它將查詢請求遞交給IndexSearcher完成搜尋操作。Query擁有許多子類以完成不同的查詢請求。例如TermQuery是按詞條搜尋,它是最基本最簡單的查詢類型,用來在指定域中匹配特定項的文檔;RangeQuery,指定範圍內搜尋,用於在指定域中匹配特定範圍內的文檔;FuzzyQuery,一種模糊查詢,能夠簡單地識別近義詞匹配與查詢關鍵字語義相近的項。

QueryParser,Query解析器。需要實現不同的查詢需求時必須使用Query提供的不同子類,導致Query使用起來容易造成混亂。因而Pylucene還提供了Query文法解析器QueryParser。QueryParser能夠解析提交的Query語句,根據Query文法挑選合適Query子類完成相應的查詢,開發人員不必關心底層使用的是什麼Query實作類別。例如Query語句“關鍵字1 and 關鍵字2” QueryParser解析為查詢同時匹配關鍵字1和關鍵字2的文檔;Query語句“id[123 to 456]” QueryParser解析成為查詢名稱為“id”的域中的值在指定範圍“123”到“456”之間的文檔;Query語句“關鍵字 site:www.web.com”QueryParser解析成為查詢同時滿足名稱為“site”的域中值為“www.web.com” 和匹配“關鍵字”兩個查詢條件的文檔。

索引的搜尋是Pylucene所專註的領域之一,為實現索引的搜尋編寫了一個名為query的類,query實現索引的搜尋有以下主要步驟:

lucene.initVM()if query_str.find(":") ==-1 and query_str.find(":") ==-1:query_str="title:"+query_str+" OR content:"+query_str①indir= SimpleFSDirectory(File(self.__indexDir))②lucene_analyzer= CJKAnalyzer(Version.LUCENE_CURRENT)③lucene_searcher= IndexSearcher(indir)④my_query = QueryParser(Version.LUCENE_CURRENT,"title",lucene_analyzer).parse(query_str)⑤total_hits = lucene_searcher.search(my_query, MAX)⑥for hit in total_hits.scoreDocs:⑦            print"Hit Score: ", hit.score            doc = lucene_searcher.doc(hit.doc)            result_urls.append(doc.get("url").encode("utf-8"))            result_titles.append(doc.get("title").encode("utf-8"))            print doc.get("title").encode("utf-8")  result = {"Hits": total_hits.totalHits, "url":tuple(result_urls), "title":tuple(result_titles)} return result

索引的搜尋有7個主要的步驟:

①首先對搜尋語句進行判斷,若語句不是針對標題或文章內容進行單一域的查詢,即不包含關鍵詞“title:”或“content:”時預設搜尋title和content兩個域。

②執行個體化一個SimpleFSDirectory對象,指定它的工作路徑為先前建立索引的路徑。

③執行個體化一個CJKAnalyzer分析器,搜尋時使用的分析器應與索引構建時使用的分析器在類型版本上均一致。

④執行個體化一個IndexSearcher對象lucene_searcher,它的參數為第○2步的SimpleFSDirectory對象。

⑤執行個體化一個QueryParser對象my_query,它描述查詢請求,解析Query查詢語句。參數Version.LUCENE_CURRENT為pylucene的版本號碼,“title”指預設的搜尋域,lucene_analyzer指定了使用的分析器,query_str是Query查詢語句。在執行個體化QueryParser前會對使用者搜尋請求作簡單處理,若使用者指定了搜尋某個域就搜尋該域,若使用者未指定則同時搜尋“title”和“content”兩個域。

⑥lucene_searcher進行搜尋操作,返回結果集total_hits。total_hits中包含結果總數totalHits,搜尋結果的文檔集scoreDocs,scoreDocs中包括搜尋出的文檔以及每篇文檔與搜尋語句相關度的得分。

⑦lucene_searcher搜尋出的結果集不能直接被Python處理,因而在搜尋操作返回結果之前應將結果由Pylucene轉為普通的Python資料結構。使用For迴圈依次處理每個結果,將結果文檔按相關度得分高低依次將它們的地址域“url”的值放入Python列表result_urls,將標題域“title”的值放入列表result_titles。最後將包含地址、標題的列表和結果總數組合成一個Python“字典”,將最後處理的結果作為整個搜尋操作的傳回值。

使用者在瀏覽器搜尋方塊輸入搜尋字詞並點擊搜尋,瀏覽器發起一個GET請求,Flask的路由route設定了由result函數響應該請求。result函數先執行個體化一個搜尋類query的對象infoso,將搜尋字詞傳遞給該對象,infoso完成搜尋將結果返回給函數result。函數result將搜尋出來的頁面和結果總數等傳遞給模板result.html,模板result.html用於呈現結果

如下是Python使用flask模組處理搜尋請求的代碼:

app = Flask(__name__)#建立Flask執行個體

@app.route('/')#設定搜尋預設首頁

def index():html="<h1>title這是標題</h1>"return render_template('index.html')@app.route("/result",methods=['GET', 'POST'])#註冊路由,並指定HTTP方法為GET、POSTdef result(): #resul函數if request.method=="GET":#響應GET請求key_word=request.args.get('word')#擷取搜尋語句   if len(key_word)!=0:      infoso = query("./glxy") #建立查詢類query的執行個體       re = infoso.search(key_word)#進行搜尋,返回結果集       so_result=[]       n=0       for item in re["url"]:temp_result={"url":item,"title":re["title"][n]}#將結果集傳遞給模板        so_result.append(temp_result)                n=n+1        return render_template('result.html', key_word=key_word, result_sum=re["Hits"],result=so_result)    else:        key_word=""    return render_template('result.html')if __name__ == '__main__':    app.debug = True    app.run()#運行web服務
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.