搜尋
首頁後端開發Python教學python實作一個搜尋引擎(Pylucene)實例教程

  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鏈接放進隊列,再從隊列中取出新的節點進行訪問,直至隊列為空。透過佇列「先進先出」的特性實現廣度優先的遍歷演算法,逐一造訪網站的每一頁。

 

                             有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_dir
indexdir = 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 id="title这是标题">title这是标题</h1>"
return render_template(&#39;index.html&#39;)
@app.route("/result",methods=[&#39;GET&#39;, &#39;POST&#39;])#注册路由,并指定HTTP方法为GET、POST
def result(): #resul函数
if request.method=="GET":#响应GET请求
key_word=request.args.get(&#39;word&#39;)#获取搜索语句
   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(&#39;result.html&#39;, key_word=key_word, result_sum=re["Hits"],result=so_result)
    else:
        key_word=""
    return render_template(&#39;result.html&#39;)
if __name__ == &#39;__main__&#39;:
    app.debug = True
    app.run()#运行web服务


以上是python實作一個搜尋引擎(Pylucene)實例教程的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
Python中有可能理解嗎?如果是,為什麼以及如果不是為什麼?Python中有可能理解嗎?如果是,為什麼以及如果不是為什麼?Apr 28, 2025 pm 04:34 PM

文章討論了由於語法歧義而導致的Python中元組理解的不可能。建議使用tuple()與發電機表達式使用tuple()有效地創建元組。 (159個字符)

Python中的模塊和包裝是什麼?Python中的模塊和包裝是什麼?Apr 28, 2025 pm 04:33 PM

本文解釋了Python中的模塊和包裝,它們的差異和用法。模塊是單個文件,而軟件包是帶有__init__.py文件的目錄,在層次上組織相關模塊。

Python中的Docstring是什麼?Python中的Docstring是什麼?Apr 28, 2025 pm 04:30 PM

文章討論了Python中的Docstrings,其用法和收益。主要問題:Docstrings對於代碼文檔和可訪問性的重要性。

什麼是lambda功能?什麼是lambda功能?Apr 28, 2025 pm 04:28 PM

文章討論了Lambda功能,與常規功能的差異以及它們在編程方案中的效用。並非所有語言都支持他們。

什麼是休息時間,繼續並通過python?什麼是休息時間,繼續並通過python?Apr 28, 2025 pm 04:26 PM

文章討論了休息,繼續並傳遞Python,並解釋了它們在控制循環執行和程序流中的作用。

Python的通行證是什麼?Python的通行證是什麼?Apr 28, 2025 pm 04:25 PM

本文討論了Python中的“ Pass”語句,該語句是函數和類等代碼結構中用作佔位符的空操作,允許在沒有語法錯誤的情況下實現將來實現。

我們可以在Python中傳遞作為參數的函數嗎?我們可以在Python中傳遞作為參數的函數嗎?Apr 28, 2025 pm 04:23 PM

文章討論了將功能作為Python中的參數,突出了模塊化和用例(例如分類和裝飾器)等好處。

Python中的 /和//有什麼區別?Python中的 /和//有什麼區別?Apr 28, 2025 pm 04:21 PM

文章在Python中討論 /和//運營商: / for for True Division,//用於地板部門。主要問題是了解它們的差異和用例。 Character數量:158

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

EditPlus 中文破解版

EditPlus 中文破解版

體積小,語法高亮,不支援程式碼提示功能

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

mPDF

mPDF

mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

DVWA

DVWA

Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中