董 哲 祝福松
(北方工業(yè)大學(xué) 電氣與控制工程學(xué)院,北京 100043)
當(dāng)前在食品安全領(lǐng)域,食品安全信息的獲取主要依靠百度谷歌等通用搜索引擎,無法滿足人們對食品安全信息快速、精確查找的需求。隨著搜索引擎技術(shù)快速發(fā)展,國內(nèi)外出現(xiàn)了許多面向各領(lǐng)域的垂直搜索引擎,但能夠搜索食品安全信息的引擎較少。曹奇峰在文獻[1]中提出基于Nutch的食品安全信息垂直搜索引擎的研究。通過Nutch框架對相關(guān)食品安全主題網(wǎng)頁進行爬取建立索引庫,綜合評分算法將索引內(nèi)容進行排序,最終給出搜索結(jié)果。王亮等人在文獻[2]中設(shè)計了食品安全科普網(wǎng)站的建立,提出了個性化的搜索引擎,通過對用戶搜索日志的挖掘,發(fā)現(xiàn)不同搜索在時序上的關(guān)聯(lián),并利用這些關(guān)聯(lián)對新的用戶搜索進行擴展,給出延伸的搜索結(jié)果。搜索引擎的建立大同小異,區(qū)別在于資源庫的建立,與搜索引擎的排序算法。本文采用的是基于ES構(gòu)建搜索引擎架構(gòu),使用Scrapy-redis分布式爬蟲構(gòu)建食品安全資源庫,在性能上和速度上更優(yōu)。通過對此搜索引擎的建立過程,涉及對目標(biāo)網(wǎng)站的爬取,對資源的去重清洗,以及對資源庫系統(tǒng)的建立過程,就可以適用于其他資源庫的建設(shè)中,其具有很好的通用性。
本系統(tǒng)被分為四個模塊。分別是:爬蟲模塊,搜索模塊,數(shù)據(jù)可視化模塊,后端數(shù)據(jù)處理模塊。
從特定網(wǎng)站中按照爬取策略爬取相關(guān)內(nèi)容,并將爬取到的內(nèi)容進行清洗、去重等處理,并保存到本地數(shù)據(jù)庫中。
索引過程,將爬取到的資源庫,保存到ES中。搜索過程,為用戶提供搜索服務(wù)。
用戶輸入搜索內(nèi)容,及顯示搜索結(jié)果。
用于API解析與處理,如圖1所示。
圖1 系統(tǒng)總體架構(gòu)
爬蟲是根據(jù)既定的要求,有目的地篩選所有符合條件的URL進行爬取,并根據(jù)要求提取文本信息,爬蟲模塊的設(shè)計是在基于Scrapy-redis組件的基礎(chǔ)上進行進行功能的擴展,主要模塊包括頁面爬取功能子模塊,URL過濾功能子模塊,文本相似過濾功能子模塊。
1.1 Scrapy爬蟲系統(tǒng)及反反爬蟲策略
Scrapy主要包含引擎(Scrapy Engine)、調(diào)度器(Scheduler)、下載器(Downloader)、爬蟲(Spiders)、項目管道(Item Pipeline)、下載器中間件(Downloader Middlewares)、爬蟲中間件(Spider Middlewares)、調(diào)度中間件(Scheduler Middlewares)。
Engine是整個框架的“大腦”,控制爬蟲的運行。Spider通過自定義設(shè)置控制Engine向調(diào)度器發(fā)送指令,調(diào)度器得到指令后處理后發(fā)送請求給下載器,下載器根據(jù)接受的請求從互聯(lián)網(wǎng)下載相關(guān)鏡像到本地,再傳遞給spiders,spiders對數(shù)據(jù)進行處理,之后將數(shù)據(jù)傳入項目管道保存或輸出,獲取的URL發(fā)送到Engine進行驗證處理,已爬取的URL會被丟掉,未爬取的URL排序后傳遞到調(diào)度器待下載隊列,準(zhǔn)備下一步抓取。只要調(diào)度器不為空,爬蟲將一直運行下去[3],如圖2所示。
圖2 爬蟲的基本流程圖
為了爬取網(wǎng)頁內(nèi)容,提取相關(guān)字段,在本文中采用xpath正則表達(dá)式來匹配相關(guān)字段,選擇相應(yīng)DOM元素,將其下載到items中,最后保存到數(shù)據(jù)庫中。在本文中,將爬取的目標(biāo)選擇了食品伙伴網(wǎng)(http://www.foodmate.net/) ,相對應(yīng)字段的Xpath表達(dá)式為:
對于本次反反爬蟲策略,主要采用的是設(shè)置User-Agent,通過github上開源模塊fake-useragent模塊來動態(tài)的改變User-Agent值從而直接更改header中的User-Agent值來達(dá)到目的。
1.2 分布式爬蟲
在本文中,爬蟲模塊是基于Scrapy-Redis分布式爬蟲主從架構(gòu)構(gòu)建而成,使用Redis服務(wù)器作為任務(wù)隊列,將主服務(wù)器作為控制節(jié)點負(fù)責(zé)所有從服務(wù)器運行網(wǎng)絡(luò)爬蟲的主機進行管理,爬蟲只需要從控制節(jié)點那里接收任務(wù),并把新生成任務(wù)提交給控制節(jié)點,如圖3所示。
圖3 分布式爬蟲的策略示意圖
其中,主服務(wù)器主要負(fù)責(zé)URL去重和任務(wù)分配,而從服務(wù)器主要負(fù)責(zé)爬蟲任務(wù)。
在進行數(shù)據(jù)爬取時,若不進行URL去重,不僅會降低爬蟲的效率,還會造成儲存資源的浪費。Scrapy框架默認(rèn)的URL去重方法由dupefilters去重器通過RFPDupeFilter 類實現(xiàn),RFPDupeFilter類會對每一個請求生成信息指紋fp,但是這種URL去重方法比較耗費內(nèi)存,而本文采用的是通過Bloom Filter算法的布隆過濾器就可以很好的改進這個問題。
Scrapy-redis默認(rèn)的去重模塊RFPDupeFilter主要通過fp(指紋)標(biāo)準(zhǔn)過濾,去重結(jié)構(gòu)使用的是redis中的集合(set)實現(xiàn)去重功能。在計算機中通過鏈表的數(shù)據(jù)結(jié)構(gòu)來儲存集合,而redis是內(nèi)存數(shù)據(jù)庫,也就意味著所有爬取的請求、數(shù)據(jù),去重集合都會存在內(nèi)存中,請求隊列會隨著爬取的進行。動態(tài)出入,不會無限疊加,爬取到的數(shù)據(jù)一般會轉(zhuǎn)移到其他數(shù)據(jù)庫,也不會無限疊加,但去重集合會隨著爬取的進行,添加新的指紋,導(dǎo)致占用的內(nèi)存空間不斷增大,最終可能影響系統(tǒng)的性能。而布隆過濾器這種比較巧妙的概率型數(shù)據(jù)結(jié)構(gòu)相比于傳統(tǒng)的List、Set、Map等數(shù)據(jù)結(jié)構(gòu),更高效,占用空間更少。
該模塊通過Scrapy提供的Item pipeline組件機制實現(xiàn)了一個對文本去重的方法類,通過編寫pipeline組件里的類方法,規(guī)定它的執(zhí)行順序,實現(xiàn)當(dāng)網(wǎng)絡(luò)爬蟲的數(shù)據(jù)items通過時,與已經(jīng)入庫的數(shù)據(jù)進行相似度判別,相似度較高的items將被丟棄,否則進入下一個pipeline中,直至被保存到數(shù)據(jù)庫中。
在本文中,對文本相似度判別的類方法是基于SimHash算法[4],它通過調(diào)用Jieba分詞,對字段內(nèi)容進行分詞,運用TF-IDF算法從中提取帶有權(quán)重的關(guān)鍵詞特征向量列表,然后將得到的關(guān)鍵詞特征向量列表傳給simHash類中,simHash類實現(xiàn)Simhash算法的全部流程(關(guān)鍵詞特征向量→哈希→加權(quán)→累加→二值化),進而得到該文本64位二進制SimHash值,如果待測文本的SimHash值存在于語義指紋庫中的,則可以直接判定重復(fù),否則將比較待測文本與語義指紋庫SimHash值的海明距離,一般海明距離小于等于3,則為相似,如 圖4所示。
圖4 文本去重的主要流程圖
4.1 ES全文搜索
ES是一款基于Lucene的開源工具包,支持分布式的搜索引擎框架,可以實現(xiàn)海量數(shù)據(jù)的快速儲存和搜索,提供了多種RESTful 風(fēng)格的Web接口,能夠解決各種用例,達(dá)到實時搜索的目的。是目前企業(yè)級應(yīng)用最為常見的搜索引擎框架之一[5]。本文中,采用ES進行全文搜索主要包括兩個過程:索引過程和搜索過程,如圖5所示。
圖5 食品安全搜索整體架構(gòu)圖
由系統(tǒng)的總體整體架構(gòu)可以看出,食品安全搜索引擎的核心是ES服務(wù)器,用于食品安全相關(guān)信息的存儲,同時返回基于RESTful Web的數(shù)據(jù)接口,返回的數(shù)據(jù)格式為JSON形式,進而方便數(shù)據(jù)的二次處理和利用。
4.2 ES索引和搜索過程
ES在索引過程中是將爬蟲爬取到的數(shù)據(jù)保存并根據(jù)映射定義的字段類型進行分詞,然后構(gòu)建倒排索引,最后把數(shù)據(jù)轉(zhuǎn)換成JSON格式存放在文檔里。搜索過程是根據(jù)用戶輸入的關(guān)鍵字匹配倒排索引表中的文檔集合,然后對文檔進行評分,排序,高亮等處理,最后把搜索結(jié)果返回給用戶。
ES全文搜索具體的步驟為:在上面爬蟲模塊中,已經(jīng)從爬蟲系統(tǒng)的pipeline中得到了經(jīng)過去重處理之后返回的items對象,此時需要在pipeline中使用Elasticsearch-dsl將爬取到的items對象建立索引并保存到ES 中。當(dāng)用戶輸入關(guān)鍵詞進行搜索時,前端界面會根據(jù)關(guān)鍵詞顯示搜索建議,通過ES搜索建議接口Completion Suggester實現(xiàn)自動補全功能,后端接收到用戶的搜索內(nèi)容,經(jīng)過數(shù)據(jù)分析,將關(guān)鍵詞發(fā)送給ES服務(wù)器,并向ES數(shù)據(jù)庫請求索引內(nèi)容,最后將匹配到的文檔集合返回給前端界面顯示搜索內(nèi)容。
食品安全搜索引擎頁面的實現(xiàn)主要包括后端數(shù)據(jù)處理模塊和前端數(shù)據(jù)可視化模塊,主要用于用戶輸入搜索內(nèi)容,返回搜索結(jié)果,及搜索結(jié)果的可視化。本文是基于Vue和Django搭建前后端分離的Web項目。使用前后端分離的思想主要是為了解耦合和網(wǎng)站的維護,以及之后可以在此食品安全搜索引擎的基礎(chǔ)上完善其他有關(guān)食品安全的內(nèi)容,搭建一個有關(guān)食品安全的信息網(wǎng)站。
5.1 后端數(shù)據(jù)處理模塊
在本文中采用Django框架作為后端數(shù)據(jù)處理模塊。Django是基于Python語言針對web后端開發(fā)的大型應(yīng)用框架。它采用MVC的架構(gòu)模式,M代表Model層(數(shù)據(jù)層),負(fù)責(zé)業(yè)務(wù)對象與數(shù)據(jù)庫的對象關(guān)系映射(ORM)。C代表Controller(控制器),負(fù)責(zé)根據(jù)用戶從”視圖層”輸入的指令,選取”數(shù)據(jù)層”中的數(shù)據(jù),然后對其進行相應(yīng)的操作,產(chǎn)生最終結(jié)果。V代表View層(視圖層),它接受Web請求并且返回Web響應(yīng)。
對于前端發(fā)送的數(shù)據(jù)請求,Django中間件(Middlewares)接收到用戶請求并對request做一些預(yù)處理,通過URLconf模塊查找對應(yīng)的視圖模塊然后進行路由分發(fā),對數(shù)據(jù)請求地址進行解析,視圖層接收到請求,調(diào)用View中的函數(shù),選擇性的通過Models層訪問數(shù)據(jù)庫中的數(shù)據(jù),將返回給Views層的輸出經(jīng)過Django中間件的處理,最后將Response返回給客戶端,如圖6所示。
圖6 Django后端處理請求響應(yīng)流程圖
5.2 前端數(shù)據(jù)可視化模塊
本文前端數(shù)據(jù)可視化模塊采用基于MVVM架構(gòu)模式的Vue框架。所謂MVVM架構(gòu),如下圖7所示,Model代表模型層,主要實現(xiàn)數(shù)據(jù)的修改和操作業(yè)務(wù)邏輯;View代表視圖層,主要負(fù)責(zé)將數(shù)據(jù)模型轉(zhuǎn)化成可視化內(nèi)容; ViewModel代表視圖模型層,它是溝通模型層和視圖層的橋梁所在。ViewModel層通過雙向綁定的方式,當(dāng)模型層發(fā)生改變時,ViewModel層監(jiān)聽到模型層的變化,并通知視圖層發(fā)生改變,反之當(dāng)視圖層發(fā)生改變時會通知模型層改變。通過這種模式,可以更快地實現(xiàn)數(shù)據(jù)的響應(yīng)以及視圖的更新。
圖7 MVVM架構(gòu)
在實現(xiàn)搜索功能時,綁定搜索按鈕點擊事件HandleSearch,下面是前端實現(xiàn)搜索功能的主要程序:
5.3 食品安全搜索引擎搜索功能實現(xiàn)程序流程
在系統(tǒng)測試中爬取的目標(biāo)選擇了食品伙伴網(wǎng)(http://www.foodmate.net/),食品伙伴網(wǎng)中涵蓋了大量關(guān)于食品安全信息的新聞資訊,網(wǎng)站結(jié)構(gòu)上,反爬蟲策略相對不是太難,頁面結(jié)構(gòu)也比較簡單,很符合目前的要求。
關(guān)于爬取速度方面的測試,選用三臺服務(wù)器,一臺Master服務(wù)器和兩臺Slave服務(wù)器Master端:騰訊云服務(wù)器CPU 2核,2G內(nèi)存,IP地址(49.233.21.252),centos7.5 64位系統(tǒng); Slave端分別為: CPU 8核,8G內(nèi)存,IP地址(192.168.43.199),Windows10 64位操作系統(tǒng); CPU 2核,4G內(nèi)存,IP地址(192.168.1.107),Ubuntun18.04 64位系統(tǒng)。以食品伙伴網(wǎng)為目標(biāo),運行60分鐘,爬取到2282條數(shù)據(jù)。將爬取到的數(shù)據(jù)儲存到Mysql數(shù)據(jù)庫中。使用MySQLWorkbench可視化工具,展示部分?jǐn)?shù)據(jù)如下所示:
針對去重清洗方面,經(jīng)測試爬蟲的日志信息提示丟掉約3%與已入庫文本相似度較高的數(shù)據(jù),經(jīng)過確認(rèn),確實為重復(fù)數(shù)據(jù)。沒有出現(xiàn)不能容忍的高誤差數(shù)據(jù)。
搜索引擎界面如下所示:
搜索結(jié)果界面:
本文采用了Scrapy-redis分布式爬蟲框架進行網(wǎng)絡(luò)數(shù)據(jù)的爬取,然后經(jīng)過布隆過濾器過濾URL及SimHash算法文本去重等一系列措施,實現(xiàn)對資源庫的建立,基于Elasticsearch,構(gòu)建全文搜索引擎,實現(xiàn)用戶的快捷實時搜索。并使用Django+Vue前后端分離架構(gòu),實現(xiàn)了搜索引擎的可視化頁面和交互。本文提出的思想是設(shè)想構(gòu)建一款專門針對食品安全的信息網(wǎng)站,其中就有關(guān)于食品安全的全文搜索功能,未來還需要完善數(shù)據(jù)庫資源,以及關(guān)于食品安全的不同數(shù)據(jù)資源。