0 前言
?? 優(yōu)質(zhì)競(jìng)賽項(xiàng)目系列,今天要分享的是
?? python的搜索引擎系統(tǒng)設(shè)計(jì)與實(shí)現(xiàn)
??學(xué)長(zhǎng)這里給一個(gè)題目綜合評(píng)分(每項(xiàng)滿分5分)
- 難度系數(shù):3分
- 工作量:5分
- 創(chuàng)新點(diǎn):3分
該項(xiàng)目較為新穎,適合作為競(jìng)賽課題方向,學(xué)長(zhǎng)非常推薦!
?? 更多資料, 項(xiàng)目分享:文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-654522.html
https://gitee.com/dancheng-senior/postgraduate文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-654522.html
1 課題簡(jiǎn)介
隨著互聯(lián)網(wǎng)和寬帶上網(wǎng)的普及, 搜索引擎在中國(guó)異軍突起, 并日益滲透到人們的日常生活中, 在互聯(lián)網(wǎng)普及之前,
人們查閱資料首先想到的是擁有大量書籍的資料的圖書館。 但是今天很多人都會(huì)選擇一種更方便、 快捷、 全面、 準(zhǔn)確的查閱方式–互聯(lián)網(wǎng)。
而幫助我們?cè)谡麄€(gè)互聯(lián)網(wǎng)上快速地查找到目標(biāo)信息的就是越來(lái)越被重視的搜索引擎。
今天學(xué)長(zhǎng)來(lái)向大家介紹如何使用python寫一個(gè)搜索引擎,該項(xiàng)目常用于畢業(yè)設(shè)計(jì)
2 系統(tǒng)設(shè)計(jì)實(shí)現(xiàn)
2.1 總體設(shè)計(jì)
學(xué)長(zhǎng)設(shè)計(jì)的系統(tǒng)采用的是非關(guān)系型數(shù)據(jù)庫(kù)Elasticsearch,因此對(duì)于此數(shù)據(jù)庫(kù)的查詢等基本操作會(huì)加以圖例的方式進(jìn)行輔助闡述。在使用者開(kāi)始進(jìn)行査詢時(shí),系統(tǒng)不可能把使用者輸入的關(guān)鍵詞與所有本地?cái)?shù)據(jù)進(jìn)行匹配,這種檢索方式即便建立索引,查詢效率仍然較低,而且非常消耗服務(wù)器資源。
因此,Elasticsearch將獲取到的數(shù)據(jù)分為兩個(gè)階段進(jìn)行處理。第一階段:采用合適的分詞器,將獲取到的數(shù)據(jù)按照分詞器的標(biāo)準(zhǔn)進(jìn)行分詞,第二階段:對(duì)每個(gè)關(guān)鍵詞的頻率以及出現(xiàn)的位置進(jìn)行統(tǒng)計(jì)。
經(jīng)過(guò)以上兩個(gè)階段,最后每個(gè)詞語(yǔ)具體出現(xiàn)在哪些文章中,出現(xiàn)的位置和頻次如何,都將會(huì)被保存到Elasticsearch數(shù)據(jù)庫(kù)中,此過(guò)程即為構(gòu)建倒排索引,需要花費(fèi)的計(jì)算開(kāi)銷很大,但大大提高了后續(xù)檢索的效率。其中,搜索引擎的索引過(guò)程流程圖如圖
2.2 搜索關(guān)鍵流程
如圖所示,每一位用戶在搜索框中輸入關(guān)鍵字后,點(diǎn)擊搜索發(fā)起搜索請(qǐng)求,系統(tǒng)后臺(tái)解析內(nèi)容后,將搜索結(jié)果返回到查詢結(jié)果頁(yè),用戶可以直接點(diǎn)擊查詢結(jié)果的標(biāo)題并跳轉(zhuǎn)到詳情頁(yè),也可以點(diǎn)擊下一頁(yè)查看其他頁(yè)面的搜索結(jié)果,也可以選擇重新在輸入框中輸入新的關(guān)鍵詞,再次發(fā)起搜索。
跳轉(zhuǎn)至不同結(jié)果頁(yè)流程圖:
瀏覽具體網(wǎng)頁(yè)信息流程圖:
搜索功能流程圖:
2.3 推薦算法
用戶可在平臺(tái)上了解到當(dāng)下互聯(lián)網(wǎng)領(lǐng)域中的熱點(diǎn)內(nèi)容,點(diǎn)擊文章鏈接后即可進(jìn)入到對(duì)應(yīng)的詳情頁(yè)面中,瀏覽選中的信息的目標(biāo)網(wǎng)頁(yè),詳細(xì)了解其中的內(nèi)容。豐富了本搜索平臺(tái)提供信息的實(shí)時(shí)性,如圖
用戶可在搜索引擎首頁(yè)中瀏覽到系統(tǒng)推送的可能感興趣的內(nèi)容,同時(shí)用戶可點(diǎn)擊推送的標(biāo)題進(jìn)入具體網(wǎng)頁(yè)進(jìn)行瀏覽詳細(xì)內(nèi)容。流程圖如圖
2.4 數(shù)據(jù)流的實(shí)現(xiàn)
學(xué)長(zhǎng)設(shè)計(jì)的系統(tǒng)的數(shù)據(jù)來(lái)源主要是從發(fā)布互聯(lián)網(wǎng)專業(yè)領(lǐng)域信息的開(kāi)源社區(qū)上爬蟲(chóng)得到。
再經(jīng)過(guò)IK分詞器對(duì)獲取到的標(biāo)題和摘要進(jìn)行分詞,再由Elasticsearch建立索引并將數(shù)據(jù)持久化。
用戶通過(guò)輸入關(guān)鍵詞,點(diǎn)擊檢索,后臺(tái)程序?qū)Λ@得的關(guān)鍵詞再進(jìn)行分詞處理,再到數(shù)據(jù)庫(kù)中進(jìn)行查找,將滿足條件的網(wǎng)頁(yè)標(biāo)題和摘要用超鏈接的方式在瀏覽器中顯示出來(lái)。
3 實(shí)現(xiàn)細(xì)節(jié)
3.1 系統(tǒng)架構(gòu)
搜索引擎有基本的五大模塊,分別是:
- 信息采集模塊
- 信息處理模塊
- 建立索引模塊
- 查詢和 web 交互模塊
學(xué)長(zhǎng)設(shè)計(jì)的系統(tǒng)目的是在信息處理分析的基礎(chǔ)上,建立一個(gè)完整的中文搜索引擎。
所以該系統(tǒng)主要由以下幾個(gè)詳細(xì)部分組成:
- 爬取數(shù)據(jù)
- 中文分詞
- 相關(guān)度排序
- 建立web交互。
3.2 爬取大量網(wǎng)頁(yè)數(shù)據(jù)
爬取數(shù)據(jù),實(shí)際上用的就是爬蟲(chóng)。
我們平時(shí)在瀏覽網(wǎng)頁(yè)的時(shí)候,在瀏覽器里輸入一個(gè)網(wǎng)址,然后敲擊回車,我們就會(huì)看到網(wǎng)站的一些頁(yè)面,那么這個(gè)過(guò)程實(shí)際上就是這個(gè)瀏覽器請(qǐng)求了一些服務(wù)器然后獲取到了一些服務(wù)器的網(wǎng)頁(yè)資源,然后我們看到了這個(gè)網(wǎng)頁(yè)。
請(qǐng)求呢就是用程序來(lái)實(shí)現(xiàn)上面的過(guò)程,就需要寫代碼來(lái)模擬這個(gè)瀏覽器向服務(wù)器發(fā)起請(qǐng)求,然后獲取這些網(wǎng)頁(yè)資源。那么一般來(lái)說(shuō)實(shí)際上獲取的這些網(wǎng)頁(yè)資源是一串HTML代碼,這里面包含HTML標(biāo)簽,還有一
我們寫完程序之后呢就讓它一直運(yùn)行著,它就能代替我們?yōu)g覽器來(lái)向服務(wù)器發(fā)送請(qǐng)求,然后一直不停的循環(huán)的運(yùn)行進(jìn)行批量的大量的獲取數(shù)據(jù)了,這就是爬蟲(chóng)的一個(gè)基本的流程。
一個(gè)通用的網(wǎng)絡(luò)爬蟲(chóng)的框架如圖所示:
這里給出一段爬蟲(chóng),爬取自己感興趣的網(wǎng)站和內(nèi)容,并按照固定格式保存起來(lái):
? # encoding=utf-8
? # 導(dǎo)入爬蟲(chóng)包
? from selenium import webdriver
? # 睡眠時(shí)間
? import time
? import re
? import os
? import requests
? # 打開(kāi)編碼方式utf-8打開(kāi)
?
# 睡眠時(shí)間 傳入int為休息時(shí)間,頁(yè)面加載和網(wǎng)速的原因 需要給網(wǎng)頁(yè)加載頁(yè)面元素的時(shí)間
def s(int):
time.sleep(int)
?
? # html/body/div[1]/table/tbody/tr[2]/td[1]/input
? # http://dmfy.emindsoft.com.cn/common/toDoubleexamp.do
?
if __name__ == '__main__':
#查詢的文件位置
# fR = open('D:\\test.txt','r',encoding = 'utf-8')
# 模擬瀏覽器,使用谷歌瀏覽器,將chromedriver.exe復(fù)制到谷歌瀏覽器的文件夾內(nèi)
chromedriver = r"C:\\Users\\zhaofahu\\AppData\\Local\\Google\\Chrome\\Application\\chromedriver.exe"
# 設(shè)置瀏覽器
os.environ["webdriver.chrome.driver"] = chromedriver
browser = webdriver.Chrome(chromedriver)
# 最大化窗口 用不用都行
browser.maximize_window()
# header = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'}
# 要爬取的網(wǎng)頁(yè)
neirongs = [] # 網(wǎng)頁(yè)內(nèi)容
response = [] # 網(wǎng)頁(yè)數(shù)據(jù)
travel_urls = []
urls = []
titles = []
writefile = open("docs.txt", 'w', encoding='UTF-8')
url = 'http://travel.yunnan.cn/yjgl/index.shtml'
# 第一頁(yè)
browser.get(url)
response.append(browser.page_source)
# 休息時(shí)間
s(3)
# 第二頁(yè)的網(wǎng)頁(yè)數(shù)據(jù)
#browser.find_element_by_xpath('// *[ @ id = "downpage"]').click()
#s(3)
#response.append(browser.page_source)
#s(3)
# 第三頁(yè)的網(wǎng)頁(yè)數(shù)據(jù)
#browser.find_element_by_xpath('// *[ @ id = "downpage"]').click()
#s(3)
#response.append(browser.page_source)
?
? # 3.用正則表達(dá)式來(lái)刪選數(shù)據(jù)
? reg = r'href="(//travel.yunnan.cn/system.*?)"'
? # 從數(shù)據(jù)里爬取data。。。
? # 。travel_urls 旅游信息網(wǎng)址
? for i in range(len(response)):
? travel_urls = re.findall(reg, response[i])
?
# 打印出來(lái)放在一個(gè)列表里
for i in range(len(travel_urls)):
url1 = 'http:' + travel_urls[i]
urls.append(url1)
browser.get(url1)
content = browser.find_element_by_xpath('/html/body/div[7]/div[1]/div[3]').text
# 獲取標(biāo)題作為文件名
b = browser.page_source
travel_name = browser.find_element_by_xpath('//*[@id="layer213"]').text
titles.append(travel_name)
print(titles)
print(urls)
for j in range(len(titles)):
writefile.write(str(j) + '\t\t' + titles[j] + '\t\t' + str(urls[j])+'\n')
s(1)
browser.close()
##
3.3 中文分詞
中文分詞使用jieba庫(kù)即可
jieba 是一個(gè)基于Python的中文分詞工具對(duì)于一長(zhǎng)段文字,其分詞原理大體可分為三步:
1.首先用正則表達(dá)式將中文段落粗略的分成一個(gè)個(gè)句子。
2.將每個(gè)句子構(gòu)造成有向無(wú)環(huán)圖,之后尋找最佳切分方案。
3.最后對(duì)于連續(xù)的單字,采用HMM模型將其再次劃分。
jieba分詞分為“默認(rèn)模式”(cut_all=False),“全模式”(cut_all=True)以及搜索引擎模式。對(duì)于“默認(rèn)模式”,又可以選擇是否使用
HMM 模型(HMM=True,HMM=False)。
3.4 相關(guān)度排序
上面已經(jīng)根據(jù)用戶的輸入獲取到了相關(guān)的網(wǎng)址數(shù)據(jù)。
獲取到的數(shù)據(jù)中rows的形式如下
[(urlid1,wordlocation1_1,wordlocation1_2,wordlocation1_3…),(urlid2,wordlocation2_1,wordlocation2_2,wordlocation2_3…)]
列表的每個(gè)元素是一個(gè)元組,每個(gè)元素的內(nèi)容是urlid和每個(gè)關(guān)鍵詞在該文檔中的位置。
wordids形式為[wordid1, wordid2, wordid3…],即每個(gè)關(guān)鍵詞所對(duì)應(yīng)的單詞id
我們將會(huì)介紹幾種排名算法,所謂排名也就是根據(jù)各自的規(guī)則為每個(gè)鏈接評(píng)分,評(píng)分越好。并且最終我們會(huì)將幾種排名算法綜合利用起來(lái),給出最終的排名。既然要綜合利用,那么我們就要先實(shí)現(xiàn)每種算法。在綜合利用時(shí)會(huì)遇到幾個(gè)問(wèn)題。
1、每種排名算法評(píng)分機(jī)制不同,給出的評(píng)分尺度和含義也不盡相同
2、如何綜合利用,要考慮每種算法的效果。為效果好的給與較大的權(quán)重。
我們先來(lái)考慮第一個(gè)問(wèn)題,如何消除每種評(píng)分算法所給出的評(píng)分尺度和含義不相同的問(wèn)題。
第2個(gè)問(wèn)題,等研究完所有的算法以后再來(lái)考慮。
簡(jiǎn)單,使用歸一化,將每個(gè)評(píng)分值縮放到0-1上,1代表最高,0代表最低。
對(duì)爬去到的數(shù)據(jù)進(jìn)行排序, 有好幾種排序算法:
第1個(gè)排名算法:根據(jù)單詞位置進(jìn)行評(píng)分的函數(shù)
我們可以認(rèn)為對(duì)用戶輸入的多個(gè)關(guān)鍵詞,在文檔中,這些關(guān)鍵詞出現(xiàn)的位置越靠前越好。比如我們往往習(xí)慣在文章的前面添加一些摘要性、概括性的描述。
# 根據(jù)單詞位置進(jìn)行評(píng)分的函數(shù).
# rows是[(urlid1,wordlocation1_1,wordlocation1_2,wordlocation1_3...),(urlid2,wordlocation2_1,wordlocation2_2,wordlocation2_3...)]
? def locationscore(self,rows):
? locations=dict([(row[0],1000000) for row in rows])
? for row in rows:
? loc=sum(row[1:]) #計(jì)算每個(gè)鏈接的單詞位置總和,越小說(shuō)明越靠前
? if loc<locations[row[0]]: #記錄每個(gè)鏈接最小的一種位置組合
? locations[row[0]]=loc
?
return self.normalizescores(locations,smallIsBetter=1)
####
第2個(gè)排名算法:根據(jù)單詞頻度進(jìn)行評(píng)價(jià)的函數(shù)
我們可以認(rèn)為對(duì)用戶輸入的多個(gè)關(guān)鍵詞,在文檔中,這些關(guān)鍵詞出現(xiàn)的次數(shù)越多越好。比如我們?cè)谥付ㄖ黝}的文章中會(huì)反復(fù)提到這個(gè)主題。
# 根據(jù)單詞頻度進(jìn)行評(píng)價(jià)的函數(shù)
# rows是[(urlid1,wordlocation1_1,wordlocation1_2,wordlocation1_3...),(urlid2,wordlocation2_1,wordlocation2_2,wordlocation2_3...)]
def frequencyscore(self,rows):
counts=dict([(row[0],0) for row in rows])
for row in rows:
counts[row[0]]+=1 #統(tǒng)計(jì)每個(gè)鏈接出現(xiàn)的組合數(shù)目。 每個(gè)鏈接只要有一種位置組合就會(huì)保存一個(gè)元組。所以鏈接所擁有的組合數(shù),能一定程度上表示單詞出現(xiàn)的多少。
return self.normalizescores(counts)
第3個(gè)排名算法:根據(jù)單詞距離進(jìn)行評(píng)價(jià)的函數(shù)
我們可以認(rèn)為對(duì)用戶輸入的多個(gè)關(guān)鍵詞,在文檔中,這些關(guān)鍵詞出現(xiàn)的越緊湊越好。這是因?yàn)槲覀兏M袉卧~出現(xiàn)在一句話中,而不是不同的關(guān)鍵詞出現(xiàn)在不同段落或語(yǔ)句中。
? # 根據(jù)單詞距離進(jìn)行評(píng)價(jià)的函數(shù)。
? # rows是[(urlid1,wordlocation1_1,wordlocation1_2,wordlocation1_3...),(urlid2,wordlocation2_1,wordlocation2_2,wordlocation2_3...)]
? def distancescore(self,rows):
? # 如果僅查詢了一個(gè)單詞,則得分都一樣
? if len(rows[0])<=2: return dict([(row[0],1.0) for row in rows])
?
# 初始化字典,并填入一個(gè)很大的值
mindistance=dict([(row[0],1000000) for row in rows])
for row in rows:
dist=sum([abs(row[i]-row[i-1]) for i in range(2,len(row))]) # 計(jì)算每種組合中每個(gè)單詞之間的距離
if dist<mindistance[row[0]]: # 計(jì)算每個(gè)鏈接所有組合的距離。并為每個(gè)鏈接記錄最小的距離
mindistance[row[0]]=dist
return self.normalizescores(mindistance,smallIsBetter=1)
4 實(shí)現(xiàn)效果
熱門主題推薦實(shí)現(xiàn)
搜索界面的實(shí)現(xiàn)
查詢結(jié)果頁(yè)面顯示
查詢結(jié)果分頁(yè)顯示
查詢結(jié)果關(guān)鍵字高亮標(biāo)記顯示
4 最后
?? 更多資料, 項(xiàng)目分享:
https://gitee.com/dancheng-senior/postgraduate
到了這里,關(guān)于計(jì)算機(jī)競(jìng)賽 python的搜索引擎系統(tǒng)設(shè)計(jì)與實(shí)現(xiàn)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!