利用物件導向思想實現搜尋引擎

2020-07-16 10:05:10
要想實現一個搜尋引擎,首先要了解什麼是搜尋引擎。簡單地理解,搜尋引擎是一個系統,它可以幫助使用者去網際網路上蒐集與其檢索內容相關的資訊。

通常,一個搜尋引擎由搜尋器、索引器、檢索器以及使用者介面組成,其中各個部分的含義如下:
  • 搜尋器:其實就是我們常說的爬蟲、它能夠從網際網路中蒐集大量的資訊,並將之傳遞給索引器;
  • 索引器:理解搜尋器搜尋到的資訊,並從中抽取出索引項,儲存到內部的資料庫中,等待檢索;
  • 檢索器:根據使用者查詢的內容,在已經建立好的索引庫中快速檢索出與之相關的資訊,並做相關度評價,以此進行排序。
  • 使用者介面:其作用就是提供給使用者輸入查詢內容的視窗(例如百度、谷歌的搜尋方塊),並將檢索好的內容反饋給使用者。

由於爬蟲知識不是本節學習的重點,這裡不再做深入介紹,我們假設搜尋樣本就存在於本地磁碟中。為了方便,這裡只提供五個用於檢索的檔案,各檔案存放的內容分別如下:

# 1.txt
C語言中文網
# 2.txt
http://c.biancheng.net
# 3.txt
「C語言中文網」是一個線上學習程式設計的網站,我們發布了多套文字教學,它們都通俗易懂,深入淺出。
# 4.txt
C語言中文網成立於 2012 年初,目前已經運營了將近 7 年,我們致力於分享精品教學,幫助對程式設計感興趣的讀者。
# 5.txt
堅持做好一件事情,做到極致,讓自己感動,讓使用者心動,這就是足以傳世的作品!

下面,根據以上知識,我們先實現一個最基本的搜尋引擎:
class SearchEngineBase:
    def __init__(self):
        pass
    #搜尋器
    def add_corpus(self, file_path):  
        with open(file_path, 'rb') as fin:
            text = fin.read().decode('utf-8')
        self.process_corpus(file_path, text)
    #索引器
    def process_corpus(self, id, text):
        raise Exception('process_corpus not implemented.')
    #檢索器
    def search(self, query):
        raise Exception('search not implemented.')
#使用者介面
def main(search_engine):
    for file_path in ['1.txt', '2.txt', '3.txt', '4.txt', '5.txt']:
        search_engine.add_corpus(file_path)
    while True:
        query = input()
        results = search_engine.search(query)
        print('found {} result(s):'.format(len(results)))
        for result in results:
            print(result)
以上程式碼僅是建立了搜尋引擎的一個基本框架,它可以作為基礎類別被其他類繼承,那麼繼承自此類的類將分別代表不同的搜尋引擎,它們應該各自實現基礎類別中的 process_corpus() 和 search() 方法。

整個程式碼的執行過程是這樣的,首先將各個檢索檔案中包含的內容連同該檔案所在的路徑一起傳遞給索引器,索引器會以該檔案的路徑建立索引,等待使用者檢索。

在 SearchEngineBase 類的基礎上,下面實現了一個基本可以工作的搜尋引擎:
#繼承SearchEngineBase類,並重寫了 process_corpus 和 search 方法
class SimpleEngine(SearchEngineBase):
    def __init__(self):
        super(SimpleEngine, self).__init__()
        #建立索引時使用
        self.__id_to_texts = {}

    def process_corpus(self, id, text):
        #以檔案路徑為鍵,檔案內容為值,形成鍵值對,儲存在字典中,由此建立索引
        self.__id_to_texts[id] = text

    def search(self, query):
        results = []
        #依次檢索字典中的鍵值對,如果檔案內容中包含使用者要搜尋的資訊,則將此檔案的檔案路逕儲存在 results 列表中
        for id, text in self.__id_to_texts.items():
            if query in text:
                results.append(id)
        return results

search_engine = SimpleEngine()
main(search_engine)
執行結果為:

C語言中文網
found 3 result(s):
1.txt
3.txt
4.txt

可以看到,使用者搜尋與“C語言中文網”有關的內容,最終檢索到了 1.txt、3.txt和 4.txt 檔案中包含與之相關的內容。由此,只需要短短十來行程式碼就可以實現一個基礎的搜尋引擎。