首先展示一下項目效果圖:
前言:
本項目會指導大家從零開始開始構建一個針對於新浪新聞的搜索引擎.首先我們明確一下我們的目標和所需要做的工作:
目標:
- 構建一個搜索引擎
所需工作:
- 準備數據
- 一個搜索引擎的查詢算法
- 一個爲每個新聞的推薦其他相似新聞的算法
所以下面我會分這三個部分來介紹這個項目,目前這個項目已經開源.開源的地址:
https://github.com/lsq960124/News_Search_Engine
歡迎star.
準備數據
打造一個搜索引擎有一個很重要的基礎,就是我們需要有滿足搜索引擎的數據。我們的目標是打造一個新聞類的搜索引擎,所以我們需要得到新聞的數據。關於得到新聞的數據,我們基於下面的步驟:
- 首先獲取新浪新聞不同業務板塊下的新聞頁面的所有鏈接。
- 循環上面所有的鏈接爬取其新聞的內容信息。
以上面的步驟來看,首先我們需要一個新浪新聞鏈接的爬蟲,來爬取新浪新聞對應新聞鏈接數據。作爲一個新聞的搜索引擎,我們希望它不同與百度,新聞類的搜索引擎,應當可以按不同的新聞類別做一定的篩選,比如體育,財經...所以在我們爬取新聞的時候,還需要保存每個新聞對應的類別,也就是頻道。
從新浪新聞的主頁可以看到新浪新聞以及幫我們做好了很多新聞類別的分類。得到這個信息後,我們可以以每一個類別對應的根目錄作爲起始,來爬取這個類別下的所有新聞。我們以體育類別爲例子,其根目錄爲:http://sports.sina.com.cn/。而每個關於體育類別新聞的URL都是類似下面的組成:http://sports.sina.com.cn/china/national/2019-06-04/doc-ihvhiqay3565850.shtml。從這個規律來看,只用關鍵字“sports.sina”以及類如“2019-06-04”這樣的時間表示在這個鏈接裏面,我們就可以確定這個鏈接爲體育類別的鏈接。通過這個信息,我們可以定製一個深度優先遍歷的鏈接爬蟲。
對了,我們不會將新浪新聞的所有新聞全部爬取,新浪新聞的數據比較多,在這個項目中我們選定2000條作爲閾值,每個類別爬取2000就可以滿足項目要求了。
有了思路的支撐,我們就可以擼代碼了。代碼在git項目中可以查看,這裏只展示鏈接爬蟲的結果,我們會得到一個包含所有鏈接信息的文件 links.txt,如下圖:
在有了鏈接的本地文件之後,我們只用做一個基於內容的爬蟲,就可以爬取到所有關於鏈接對應的文章標題、內容、發佈時間等信息。這裏我們加入了一些多線程多進程的方式來加速爬取。將鏈接爬取到的內容,我們存到數據庫中。如圖:
以上是爲一個搜索引擎準備數據的過程和思路,在這一部分完成後,我們就要試圖來構建一個搜索引擎算法來製作一個搜索引擎了。
搜索引擎檢索算法
首先我們以一個常規的思路來想想怎麼做一個搜索引擎.
這可能會是很多人會想到一個辦法,當得到用戶的輸入後,我們和所有的已經爬取到的新聞計算一下相似度,然後對結果排序,這個就能實現一個搜索引擎算法了。這樣的算法可行嗎?很顯然是可行的,但是會遇到一個很嚴重的問題。
舉個例子,如果爬取到的新聞,不再是這個幾萬條,而是幾百萬,幾千萬。這時候,對每個用戶輸入,我們還是按照上面的做法,去和所有的數據計算相似度。這個過程是相當費時間的。作爲一個搜索引擎,你需要毫秒級的響應速度!這時候,應該怎麼做呢?
我們換一個思路,假如我搜的是”nba的球星",那麼搜索引擎返回給用戶的內容應當是很多需要涉及到"nba"和"球星"相關的內容新聞,而不會返回一些涉及家庭糾紛,或者國際政治這類無關新聞內容。換句話說,是否有一個算法可以只去計算與輸入相關的文檔,而拋開一些無關的文檔。這樣就能加快很多檢索的效率。
有了上面的思路,我們做了這樣的解決方案。
我們提前算出這樣一個表,這個表裏面存的是所有文檔中出現過的單詞和其所在的文檔,如下表:
單詞 | 所在文檔的文檔編號 |
nba | <2>,<30>,<42>,<55>....,<71>,<993>,<3156>,<4008> |
球星 | <1>,<5>,<56>,<91>,....,<201>,<655>,<3500> |
... | |
北京 | <9>,<18>,<70>,<120>,....,<980>,<4010>,<9000> |
這樣我們在輸入nba,球星的時候,我們可以從上面這個表中,知道nba和球星出現在了那些文檔中,那麼我們只用去和這些文檔計算相似度就行了,而其他不包含這些關鍵字的文檔,就會被我們捨去,不去計算。這樣對於每個用戶的輸入,我們的相似度計算都不是全量的,這樣節省了很多計算的效率。
這個思想就是bm25的算法原理。而上面這個表,就是我們意義上的倒排索引表。
我們再優化一下上面這個表,提出2個想法:
- 如果一個單詞在一篇文章中多次出現,那麼他的重要性是高於僅出現過一次的文章的.
- 如果一個文章很短,出現了一次某單詞.和一個文章很長,也出現了一次某單詞.那麼這個單詞在短文章的重要性高於長文章
上面的兩點是很有解釋性的,以上面2點的思想我們優化一下上面的表.
單詞 | <文檔標號,出現次數,文檔長度> |
nba | <2,2,10>,<30,1,30>,<42,3,50>,<55,2,34>....<4008,1,20> |
球星 | <1,1,10>,<5,2,40>,<56,3,15>,<91,5,50>,....,<3500,1,30> |
... | |
北京 | <9,1,34>,<18,2,80>,<70,3,44>,<120,5,24>,....,,<9000,2,60> |
可以看到上面的表中,對於每個單詞所在的文檔,我們還添加了其出現的詞頻df,文檔的長度length信息。這樣我們就可以通過BM25的公式來計算出出現過用戶輸入過的單詞的文檔,然後再重新排序,公式如下:
這就是一個搜索引擎的原理。從上面解釋的角度,具體去深究bm25算法的公式,顯得沒那麼有意義,我們重點理解其做到的內容,反而是關鍵的。最終我們製作的倒排索引表如下圖所示:
推薦其他相似新聞的算法
這裏你需要一些word2vec的基礎知識:https://blog.csdn.net/qq_41664845/article/details/82971728
推薦相似新聞的算法上,我們使用到了doc2vec,其實有很多推薦的算法,上面所使用的bm25也是一種可以拿來做現在這裏的推薦的一個算法,我們換一個角度想,推薦新聞,在沒有用戶數據的情況下,做到的也就是通過一個檢索算法,算出最相似的幾條新聞作爲其推薦新聞。
使用doc2vec在這裏是沒什麼原因的,就是覺得bm25這種雖然快速,但是從原理上更像是基於關鍵字的檢索,而doc2vec是基於神經網絡的,可以具備更多的語義信息。而且推薦的過程是離線的,從運行效率上不會要求那麼高的效率。
doc2vec的原理和word2vec基本類似,框圖如下:
在word2vec的基礎上,我們加入了一個paragraph id,這樣就將文檔加入神經網絡中訓練了,在用戶輸入時,我們將用戶輸入轉化爲對應的向量(轉化方式爲,單詞的詞向量做average)這個得到了文檔的向量表示。然後通過這個向量,與本地的模型矩陣做推理,這樣就能得到相似度最高的幾個文檔id。
總結:
在這個知識基礎上,我們已經可以搭建好一個屬於我們的搜索引擎了,也可以替換別的數據,做一個你喜歡的領域的搜索引擎。當然這個項目還處於很淺顯的階段,入門是可以入門了。最近搜狗的CEO說,搜索引擎的未來在於問答。所以,現在很多的優化方式都可以安裝問答機器人的思路來優化。之後我會介紹一下目前我負責搭建的一個問答機器人的項目。
本項目開源地址:https://github.com/lsq960124/Inverted-index-BM25
如果感覺有用,留個贊吧~~
QQ:470581985
微信:lsq960124
打賞一下作者: