索引是一种 data structure 技术,允许您从数据库文件中快速检索记录。它基于执行索引所基于的相同属性。
Python 上基于索引的搜索引擎是一种依赖于存储在倒排索引中的数据来查找答案的搜索引擎。当用户输入搜索查询时,它将扫描适当的索引以显示最接近的匹配结果,而不是一一搜索整个文档列表集。
An index 是一个只有两列的小表。第一列包含表的主键或候选键的副本。它的第二列包含一组指针,用于保存存储该特定键值的磁盘块的地址。
在 中search engine applications,这称为倒排索引。
倒排索引是为方便搜索查询而构建的索引、数据结构或数据库索引 。它的工作原理是存储从文档列表的内容(如单词或数字)到其在文档列表中的位置的数据映射。使用已映射的单词或数字,搜索过程将比在整个文档lists中逐个搜索更快、更高效。
查询或在搜索引擎中称为搜索查询的查询是基于用户在搜索引擎中输入的特定搜索词的查询,以满足他或她的信息需求。
这是使用搜索引擎发出的信息请求。每次用户在搜索引擎中输入一串字符并按“Enter”键时,都会进行搜索引擎查询。Web 应用程序将显示搜索查询结果
你应该有:
pip install pickle-mixin
我们将使用 pickle 模块来保存我们的索引文件,并在调用查询时加载索引文件。Pickle 模块可用于将 Python 对象存储到文件中。有了这个函数,我们将使用 pickle 将我们的字典 Python 保存到文件中,从而让我们更快地读取文件。
有关 Python 的更多信息:使用 Python 的 PCA:教程
为了制作倒排索引,我们将使用 Python 的字典。字典会将术语保存为键,并将文档的分数保存为值。这样,我们可以保存每个单词的数据文档和评分文档
为此,我们将使用术语“频率 — 反密集频率 (TF-IDF)”技术来计算文档的分数。
TF-IDF 是一种用于查找句子含义并消除单词袋技术缺点的技术。单词袋技术适用于文本分类或帮助机器读取数字中的单词。
import re
import sys
import json
import pickle
import math
#Argumen check
if len(sys.argv) !=3 :
print ("\n\\Use python \n\t tf-idf.py [data.json] [output]\n")
sys.exit(1)
#data argumen
input_data = sys.argv[1]
output_data = sys.argv[2]
data = open(input_data).read()
list_data = data.split("\n")
sw = open("stopword.txt").read().split("\n")
content=[]
for x in list_data :
try:
content.append(json.loads(x))
except:
continue
# Clean string function
def clean_str(text) :
text = (text.encode('ascii', 'ignore')).decode("utf-8")
text = re.sub("&.*?;", "", text)
text = re.sub(">", "", text)
text = re.sub("[\]\|\[\@\,\$\%\*\&\\\(\)\":]", "", text)
text = re.sub("-", " ", text)
text = re.sub("\.+", "", text)
text = re.sub("^\s+","" ,text)
text = text.lower()
return text
df_data={}
tf_data={}
idf_data={}
i=0;
for data in content :
tf={}
#clean and list word
clean_title = clean_str(data['book_title'])
list_word = clean_title.split(" ")
for word in list_word :
if word in sw:
continue
#tf term frequency
if word in tf :
tf[word] += 1
else :
tf[word] = 1
#df document frequency
if word in df_data :
df_data[word] += 1
else :
df_data[word] = 1
tf_data[data['url']] = tf
# Calculate Idf
for x in df_data :
idf_data[x] = 1 + math.log10(len(tf_data)/df_data[x])
tf_idf = {}
for word in df_data:
list_doc = []
for data in content:
tf_value = 0
if word in tf_data[data['url']] :
tf_value = tf_data[data['url']][word]
weight = tf_value * idf_data[word]
doc = {
'url' : data['url'],
'title' : data['book_title'],
'image' : data['image-url'],
'price' : data['price'],
'score' : weight
}
if doc['score'] != 0 :
if doc not in list_doc:
list_doc.append(doc)
tf_idf[word] = list_doc
# Write dictionary to file
with open(output_data, 'wb') as file:
pickle.dump(tf_idf, file)
if len(sys.argv) !=3 :
print ("\n\nPenggunaan\n\ttf-idf.py [data.json] [output]\n")
sys.exit(1)
input_data = sys.argv[1]
output_data = sys.argv[2]
data = open(input_data).read()
list_data = data.split("\n")
#load Stopword
sw = open("stopword.txt").read().split("\n")
content=[]
for x in list_data :
try:
content.append(json.loads(x))
except: continue
在上面的代码中,我加载了我们在抓取过程中返回的数据,并输入了一个我们不用于索引的“停用词”术语。若要运行脚本,请键入以下命令:
python3 tf-idf.py <data_json> <index_name>
是我们在执行抓取过程时得到的data set,并且是此脚本的输出,使其成为索引文件。
# Clean string function
def clean_str(text) :
text = (text.encode('ascii', 'ignore')).decode("utf-8")
text = text.lower()
text = re.sub("&.*?;", "", text)
text = re.sub(">", "", text)
text = re.sub("[\]\|\[\@\,\$\%\*\&\\\(\)\":]", "", text)
text = re.sub("-", " ", text)
text = re.sub("\.+", "", text)
text = re.sub("^\s+","" ,text)
return text
顾名思义,此函数的作用是从无用标点符号产生的数据集中清除book_title。
您应该了解三个术语:
使用这种 TF-IDF 技术,我们可以获得每个单词相对于文档的权重。每个单词的权重就是我们将用作分数值的权重。获得此权重的公式为:WEIGHT = TF * IDF
with open(output_data, 'wb') as file:
pickle.dump(tf_idf, file)
此代码用于使用 pickle 模块将字典保存到文件中。
将创建的查询脚本必须能够读取存储在早期文件中的字典。当然,如果你使用 pickle 模块保存了它,那么我们将使用 pickle 模块来读取它。
import re
import sys
import json
import pickle
#Argumen check
if len(sys.argv) != 4 :
print ("\n\nPenggunaan\n\tquery.py [index] [n] [query]..\n")
sys.exit(1)
query = sys.argv[3].split(" ")
n = int(sys.argv[2])
with open(sys.argv[1], 'rb') as indexdb:
indexFile = pickle.load(indexdb)
#query
list_doc = {}
for q in query:
try :
for doc in indexFile[q]:
if doc['url'] in list_doc :
list_doc[doc['url']]['score'] += doc['score']
else :
list_doc[doc['url']] = doc
except :
continue
#convert to list
list_data=[]
for data in list_doc :
list_data.append(list_doc[data])
#sorting list descending
count=1;
for data in sorted(list_data, key=lambda k: k['score'], reverse=True):
y = json.dumps(data)
print(y)
if (count == n) :
break
count+=1
要运行此脚本,只需在终端中键入以下命令:
python3 query.py <index_file> <n-query> <string-query>
<index_file>是我们之前在 pickle 模块中创建的index_file。
<n-query>是我们想要显示的结果数。
<string-query>是用户所需信息的关键字。
with open(sys.argv[1], 'rb') as indexdb:
indexFile = pickle.load(indexdb)
使用 pickle 模块读取文件字典并不需要很长时间。我们甚至可以使用 pickle 模块编写索引。
我们在索引上得到的分数不能作为排名参考,因为我们制作的索引只包含一克单词。因此,由多个单词组成的短语不能固定在索引的分数上。
为了解决这个问题,我们将对查询中的单词进行划分,并计算每个查询单词的分数。
for q in query:
try :
for doc in indexFile[q]:
if doc['url'] in list_doc :
list_doc[doc['url']]['score'] += doc['score']
else :
list_doc[doc['url']] = doc
except :
continue
要进行排名,我们只需要根据最高分对搜索结果进行排序。
源代码获取:公众号回复消息【code:64477
】