天天看點

python whoosh全文索引實作

作者:狂奔的橘子1
python whoosh全文索引實作

Whoosh是一個Python的開源搜尋引擎,它提供了在Python中建立,索引和搜尋文本的能力。Whoosh具有高度的可定制性,可以滿足各種搜尋需求,包括全文搜尋,模糊搜尋,範圍搜尋等。Whoosh支援多種存儲格式,如SQLite,MySQL,PostgreSQL和MongoDB等。此外,Whoosh還提供了對中文文本的索引和搜尋支援。

whoosh安裝

whoosh預設使用英文分詞,使用中文分詞需要額外安裝jieba。

pip install whoosh

# 中文分詞時需要
pip install jieba           

導入whoosh

from whoosh.fields import *
from whoosh.qparser import QueryParser
from whoosh.index import create_in
from whoosh.index import open_dir
from whoosh.sorting import FieldFacet
from jieba.analyse import ChineseAnalyzer
import os
           

定義索引字段

whoosh預設使用英文分詞,使用中文分詞需要導入jieba進行中文分詞。

# 導入中文分詞工具
analyser = ChineseAnalyzer()
# 建立索引結構
'''
建立了title和content兩個索引字段,TEXT為正文文本字段,stored=True表示将存儲該字段資料用于搜尋結果的傳回,analyzer=analyser表示使用中文分詞,
根據需要可以添加多個字段。
'''
schema = Schema(title=TEXT(stored=True, analyzer=analyser),
                content=TEXT(stored=True, analyzer=analyser),)             

當建立 Schema 對象時,使用關鍵字參數将字段名映射到字段類型。字段清單及其類型定義了要索引的内容和可搜尋的内容

常用字段解釋

whoosh.fields.ID
此類型隻将字段的整個值作為單個單元進行索引(并可選地存儲)(也就是說,它不會将字段分解為單個單詞)。這對于檔案路徑、URL、日期、類别等字段很有用。

whoosh.fields.STORED
此字段與文檔一起存儲,但未編入索引。此字段類型沒有索引且不可搜尋。這對于要在搜尋結果中顯示給使用者的文檔資訊很有用。

whoosh.fields.KEYWORD
此類型是為空格或逗号分隔的關鍵字設計的。此類型是可索引和搜尋的(并且可以選擇存儲)。為了節省空間,它不支援短語搜尋。

whoosh.fields.TEXT
此類型用于正文文本。它索引(并可選地存儲)文本并存儲術語位置,以允許短語搜尋。

whoosh.fields.NUMERIC
此類型用于數字。您可以存儲整數或浮點數。

whoosh.fields.BOOLEAN
此類型用于布爾值。

whoosh.fields.DATETIME
此類型用于時間類型。           

建立索引

索引隻需建立一次,

# 索引路徑,根據實際需要進行修改。
index_path = r"C:\index"

# 索引路徑不存在則建立,存在則調用open_dir方法打開索引
if not os.path.exists(index_path):
    os.mkdir(index_path)
    
    # 使用create_in方法建立索引,index_path為索引路徑,schema為前面定義的索引字段,indexname為索引名稱(根據需要進行修改)
    ix = create_in(index_path, schema=schema, indexname='indexname')
else:
    ix = open_dir(index_path, indexname='indexname')           

索引中添加資料

writer = ix.writer()

# 使用add_document向索引内添加内容
writer.add_document(title='使用手冊', content='XXX使用手冊') 
# 送出
writer.commit()           

搜尋

索引中添加完資料之後通過 ix.searcher()方法進行搜尋。

with ix.searcher() as searcher:
    # 單關鍵詞搜尋
    # parser = QueryParser("title", ix.schema).parse("手冊")
    
    # 多關鍵詞同時搜尋
    parser = MultifieldParser(["title", 'content'], ix.schema).parse("手冊")
    
    # 對結果進行排序
    facet = FieldFacet("title", reverse=True)
    
    # limit為搜尋結果的限制,預設為10,None為不限制。sortedby為排序規則
    results = searcher.search(parser, limit=None, sortedby=facet, terms=True)  
    
    # 列印搜尋結果
    for i in results:
        # title關鍵詞高亮
        print(i.highlights('title'))
        # content關鍵詞高亮
        print(i.highlights('content'))
        # 所有字段資訊
        print(i.fields())           
python whoosh全文索引實作

其他操作

# 删除索引
ix.delete_by_term('title','使用手冊')   # 删除title為’使用手冊‘的索引

# 清空索引
方法1:先删除索引檔案檔案夾或者索引檔案後,調用create_in重建即可。
方法2:直接調用create_in方法進行重建。
           

重新定義關鍵詞高亮

whoosh自帶的關鍵詞高亮highlights()方法,在個别情況下比對高亮關鍵詞之後丢失部分内容。

例如下圖,搜尋【天氣】時可以檢索出1條内容,調用高亮方法後傳回的結果前面丢失了一個數字【7】,在whoosh中未找到解決方法。

目前單獨寫了一個python

python whoosh全文索引實作

目前解決辦法:

單獨定義一個關鍵詞高亮的方法替代這一部分。

import re

def highlight_keywords(text, keywords):
    # 定義高亮樣式,根據需要進行修改,目前沿用的whoos預設的高亮樣式
    style = '<b class="match term0">'

    # 将關鍵詞轉換為正規表達式,并使用re.escape處理特殊字元
    pattern = "|".join(map(re.escape, keywords))

    # 使用正規表達式比對關鍵詞,并替換為高亮樣式
    result = re.sub(pattern, lambda match: style + match.group(0) + "</b>", text)

    return result           

應用到whoosh搜尋中

修改此部分代碼,15行和21行代碼是重點。

with ix.searcher() as searcher:
    # 單關鍵詞搜尋
    # parser = QueryParser("title", ix.schema).parse("手冊")
    
    # 多關鍵詞同時搜尋
    parser = MultifieldParser(["title", 'content'], ix.schema).parse("手冊")
	
    # 對結果進行排序
    facet = FieldFacet("title", reverse=True)
    
    # limit為搜尋結果的限制,預設為10,None為不限制。sortedby為排序規則
    results = searcher.search(parser, limit=None, sortedby=facet, terms=True)  
    
    # 通過query_terms()方法提取分詞結果,并轉為清單形式。
    keywords = [i[1].decode('utf-8') for i in list(results.query_terms())]
    
    # 列印搜尋結果
    for i in results:
        
        # 調用highlight_keywords()方法,将标題和關鍵詞清單傳入
        print(highlight_keywords(i['title'], keywords))
        
        # 所有字段資訊
        print(i.fields())           

結果如下:

python whoosh全文索引實作

複制所有代碼到py檔案可直接使用。