前言
前期分享的文章 仅30行代码,实现一个搜索引擎(1.0版) 中介绍了如何使用 30行 Python 代码来实现一个简易版的搜索引擎。
仔细阅读过这篇文章的小伙伴可能会产生一些疑虑,例如:
- 索引函数每次需要遍历所有文件,需要占用大量的时间和空间,当需被检索的文件及内容量比较大时,每次遍历检索的时间复杂度和空间复杂度就会相当高了。
- 检索的文本内容只支持单个单词,如果想一次检索多个词呢,且被检索的词分布在检索文件里的不同位置。
针对以上的疑虑,该如何进行优化呢?
最容易想到的就是将文件内容进行分词,也称语料分词
,它的思想是将整个文件内容,按照一定规则处理后形成一个无重复单词的 set 集合,语料分词
的做法可以大大提升存储和检索效率。
具体的 Python 代码实现请往下阅读。
Python 核心代码实现
代码语言:javascript复制import re
from BaseEngine import SearchEngineBase, main
class BOWModelEngine(SearchEngineBase):
def __init__(self):
"""
1.super(BOWModelEngine, self).__init__()含义是指:对继承自父类的属性使用父类的初始化方法进行初始化。
2.这里的__init__()括号里可以加上父类中初始化时定义的属性,因为此处父类初始化时没有定义任何属性,所以这里括号里为空。
"""
super(BOWModelEngine, self).__init__()
self.__file_path_to_content = {} # 子类BOWModelEngine自定义的私有属性
def process_search_contents(self, file_path, content):
"""
该函数实现功能:重写了父类的process_search_contents方法,填充__file_path_to_content字典内容,
key为文件名称,value为文件内容经过一定规则进行处理过的无重复的单词set。
:param file_path: 完整路径下的文件名称,例如:/search_contents/1.txt
:param content: 具体文件内容
:return:填充__file_path_to_content字典内容
"""
self.__file_path_to_content[file_path] = self.parse_text_to_words(content)
def search(self, query_content):
"""
该函数实现功能:重写了父类的search方法,返回检索文本中每个单词都出现在同一个文件的文件名称列表
:param query_content:需要检索的文本
:return:出现在哪些文件里的文件名称列表
"""
query_words = self.parse_text_to_words(query_content)
results = []
for file_path, content in self.__file_path_to_content.items():
if self.query_match(query_words, content):
results.append(file_path)
return results
@staticmethod
def query_match(query_words, content):
"""
该函数实现功能:遍历parse_text_to_words函数返回的无重复的单词set,判断如果有一个单词不存在于当前文件中,则返回False,否则返回True
:param query_words: 无重复的单词set
:param content: 每个文件的具体内容
:return: True&False
"""
for query_word in query_words:
if query_word not in content:
return False
return True
@staticmethod
def parse_text_to_words(content):
"""
该函数实现功能:将检索文本内容进行一定规则处理后返回无重复的单词set(集合)
:param content: 检索文本,例如:we will alive long
:return: 无重复单词的集合,格式为:{'we','will','alive'}
"""
content = re.sub(r'[^w ]', ' ', content) # 使用正则表达式去除标点符号和换行符
content = content.lower() # 搜索文本全部转换为小写
word_list = content.split(' ') # 使用空格将文本内容进行分隔,生成所有单词的列表
word_list = filter(None, word_list) # 生成的单词列表再去除空白单词
return set(word_list) # 返回单词的set(无重复的集合), 格式为: {'we','will','alive'}
search_engine = BOWModelEngine() # 实例化子类BOWModelEngine的对象
main(search_engine)
PS:
1.核心代码块中每个函数实现的功能都有详细的解释说明,请注意仔细阅读,这将非常有助于理解搜索引擎的执行流程和代码流的流转。
2.检索文件内容和被继承的基类SearchEngineBase
实现代码都是和 仅30行代码,实现一个搜索引擎(1.0版) 这篇文章中所使用的内容是一模一样的,本次只优化了继承父类的子类实现代码。
实现效果预览
至此,一个功能提升的进阶版搜索引擎就实现了,后续还会继续分享功能更加强大搜索引擎实现的高阶版,敬请关注~