悟空搜索引擎是华为诺亚方舟实验室的研究者提出的大规模的中文的跨模态数据库。
本文将以最简洁的方法讲述如何依据该数据集搭建一个自己的图片搜索引擎
数据集查看
首先从官网下载数据集 华为诺亚悟空数据集
会获得一个CSV文件,我们首先用代码查看其具体结构
with open("wukong50k_release.csv","r",encoding="utf-8") as f:
reader = csv.reader(f)
for line in reader:
print(line)
#输出
#['url', 'caption']
#['<https://gimg2.baidu.com/image_search/src=http%3A%2F%2F5b0988e595225.cdn.sohucs.com%2Fimages%2F20200326%2Fffc00cb6bc944e5b9ab2673c4873b24c.jpeg&refer=http%3A%2F%2F5b0988e595225.cdn.sohucs.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1632531279&t=1b9ba84f70ddebdda6601a5576d37c50>', '美沃可视数码裂隙灯,检查眼前节健康状况']
#['<https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fcbu01.alicdn.com%2Fimg%2Fibank%2F2020%2F527%2F038%2F17187830725_1528924397.220x220.jpg&refer=http%3A%2F%2Fcbu01.alicdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1632524815&t=d66159b43fb0335c11898f9764847ea7>', '欧美夏季ebay连衣裙 气质圆领通勤绑带收腰连衣裙 zc3730']
# ......
从结果中我们可以看出,csv数据集主要包含两列,一列是代表图片的url,使用Get方法访问该url可以直接获取图片,另一列就是图片的中文标注了。
索引的建立
搜索引擎中非常关键的一步就是数据索引的建立,关于搜索引擎的具体原理可以见其他文章
简单来说,对于一个中文搜索引擎,输入的搜索关键词就是一个个中文,而索引就是把这些中文建立到对应的图片url上。
'美沃可视数码裂隙灯,检查眼前节健康状况'
'蚂蚁摄影宝典上册 64个生活场景学参数 入门书籍教程拍摄技巧'
'北宋吉州窑云龙纹梅瓶 仿古瓷器顾问那古董老货旧货民间收藏送礼'
查看上图中的图片标签,不难观察到每个图片url所对应到的是一串比较长的字符串,这是不方便进行索引同时具备较差的灵活性的。例如”北宋吉州窑云龙纹梅瓶“,如果使用该词作为索引,那么就必须输入完整的名字,”北宋“,”云龙纹“都无法搜到相关信息。
因此理想的情况是将最小的词单位作为索引,保证搜索的鲁棒性。这里我们使用了python中Jieba分词,具体原理这里不阐述。使用方法也比较简单,pip并导入jieba包,在代码中使用cut方法就可以获得分词结果。其中cut_all用来规定分词的粒度,当设置为True时,会返回多个分词结果。
with open("wukong50k_release.csv","r",encoding="utf-8") as f:
reader = csv.reader(f)
for line in reader:
cutRes = jieba.cut(line[1],cut_all=True)
for word in cutRes:
print(word)
print("")
# with open("D:
#输出
#美 沃 可视 数码 裂隙 灯 , 检查 眼前 节 健康 健康状况 状况
#蚂蚁 摄影 宝典 上册 64 个 生活 场景 学 参数 入门 书籍 教程 拍摄 技巧
#北宋 吉州窑 云龙 龙纹 梅 瓶 仿古 瓷器 顾问 那 古董 老 货 旧货 民间 收藏 送礼
从输出中可以看到,原本的长标签被划分成了不同的短词,这样即使输入”龙纹“,”吉州“也可以搜索到”北宋吉州窑云龙纹梅瓶“。接下来我们便可以使用这些短词建立我们的索引。
为了减轻存储压力,我们使用两个文件来存储索引信息,一个是为每个url进行编号,进行编号到url的索引,另一个就是建立短词到url编号的索引。
imgs = {}
wordDict = {}
sys.stdout = io.TextIOWrapper(sys.stdout.buffer,encoding='utf8')
with open("wukong50k_release.csv","r",encoding="utf-8") as f:
reader = csv.reader(f)
for line in reader:
imgs[index] = line[0]
cutRes = jieba.cut(line[1],cut_all=True)
for word in cutRes:
#去除空格 和一些非法结果
word = word.strip()
if word == "" or word == ",":
continue
#将网页index添加到wordDict中
if word in wordDict.keys():
wordDict[word].append(index)
else:
wordDict[word] = [index]
index = index + 1
我们使用两个变量存储索引,其中img用来存储id到网页url的映射,wordDict存储词语到网页id的映射。这里需要注意一个词语对应可能不止一个网页,因此这里使用append进行添加。
运行以上代码,我们会获得如下所示的运行结果,其中每个短词对应多个id,每个id对应一个图片url
到这里我们的索引搭建完毕,就可以存储信息方便使用了
with open("wukongDict.csv","r+",encoding="utf-8") as f:
keys = list(wordDict.keys())
values = list(wordDict.values())
writer = csv.writer(f, lineterminator='\n')
for x in range(len(wordDict)):
temp = [keys[x]]
for y in values[x]:
temp.append(y)
writer.writerow(temp)
with open("wukongIndex.csv","r+",encoding="utf-8") as f:
keys = list(imgs.keys())
values = list(imgs.values())
writer = csv.writer(f, lineterminator='\n')
for x in range(len(imgs)):
temp = [keys[x]]
temp.append(values[x])
writer.writerow(temp)
接下来,为我们的索引创建一个应用,我们就可以通过输入关键词来获得结果图片链接了。当然在真正的搜索场景中需要对结果进行一个排序,使用算法对相关度进行排序,这里不做处理。
import csv
import io
import sys
import jieba
sys.stdout = io.TextIOWrapper(sys.stdout.buffer,encoding='utf8')
wordDict = {}
index = {}
def load():
indexFile = open("wukongIndex.csv","r",encoding="utf-8")
wordFile = open("wukongDict.csv","r",encoding="utf-8")
indexes = csv.reader(indexFile)
words = csv.reader(wordFile)
for line in indexes:
index[line[0]] = line[1]
for line in words:
wordDict[line[0]] = []
for i in range(1,len(line)):
wordDict[line[0]].append(line[i])
def keywordSearch(keyword):
result = []
pageIndex = wordDict[keyword]
for i in pageIndex:
result.append(index[i])
return result
def wukongSearch(input):
result = []
sourceWord = jieba.cut(input,cut_all=True)
for word in sourceWord:
result.append(keywordSearch(word))
return result
while True:
print("请输入搜索词")
search = input()
load()
idx = 0
for result in wukongSearch(search):
for word in result:
print(idx,word)
idx = idx + 1
这样,你就搭好了一个简易的搜索引擎并可以在上面进行优化了,使用的截图如下:
随意打开链接后就可以看到对应的图片