鄭洪源
[摘 要]目前,在國內(nèi)高校中程序設(shè)計課程的資源庫建設(shè)工作尚未普及,大多數(shù)教學(xué)資源存在較為嚴(yán)重的老舊、重復(fù)等問題,難以滿足師生日益增長的對大量新穎教學(xué)資源的需求。針對現(xiàn)在流行的網(wǎng)絡(luò)爬蟲框架進(jìn)行分析和選擇,在現(xiàn)有框架的基礎(chǔ)上設(shè)計了一種適合資源庫建設(shè)的爬蟲系統(tǒng),利用爬蟲的自動化特性完成教學(xué)資源庫的內(nèi)容獲取及入庫工作。同時,選用Scrapy-redis對爬蟲進(jìn)行拓展,利用Redis實現(xiàn)對目標(biāo)網(wǎng)站資源的分布式爬取,提高獲取資源的速度。選用SimHash算法對爬取到的資源內(nèi)容進(jìn)行相似度判別,過濾掉相似度過高的資源,完成對資源庫的增量更新,提高獲取到的資源的質(zhì)量。經(jīng)測試,研究的系統(tǒng)初步滿足資源庫建設(shè)的自動化需求,能夠獲取有效的教學(xué)資源。
[關(guān)鍵詞]資源庫;網(wǎng)絡(luò)爬蟲;分布式爬取;SimHash算法
[中圖分類號] G64 [文獻(xiàn)標(biāo)識碼] A [文章編號] 2095-3437(2019)09-0076-04
無論在國內(nèi)還是國外,計算機(jī)類學(xué)生必修的程序設(shè)計這門課程對于教學(xué)資源及時更新的需求益發(fā)迫切,太過陳舊的教學(xué)資源和試題不利于對學(xué)生的培養(yǎng)。由于學(xué)生可以在考前通過各種途徑獲取歷年考試真題,通過記憶考試題目便可以獲得高分??碱}陳舊、相似度高,使得考試環(huán)節(jié)的權(quán)威性、有效性大打折扣,這不利于檢驗學(xué)生的真實水平,也會導(dǎo)致教師教學(xué)資源的缺乏。
教學(xué)資源庫的建設(shè)目標(biāo)是以為師生的教與學(xué)提供優(yōu)質(zhì)服務(wù)為最終目的,以整合教學(xué)資源為主要方法,使得教師在備課過程中更加高效、更加充實,讓學(xué)生在課下學(xué)習(xí)時更加自由、更加便捷。其發(fā)展趨勢主要呈以下兩個特點:1.資源選擇便捷化。教師利用本學(xué)科的資源庫充實課程內(nèi)容時,將可以更加快捷地對資源庫進(jìn)行篩選。節(jié)約教師查找內(nèi)容的時間,提高獲取合適資源的準(zhǔn)確度,使教師有更多的時間去創(chuàng)新,反向充實資源庫,形成良性循環(huán)。2.系統(tǒng)服務(wù)個性化。針對教師的教學(xué)內(nèi)容、課程對學(xué)生等級、學(xué)習(xí)階段等的不同要求,根據(jù)對教師信息的匯總和系統(tǒng)識別,為教師提供滿足自身需求的準(zhǔn)確服務(wù),提高系統(tǒng)資源的可用性。
一、目的和意義
本研究利用主題網(wǎng)絡(luò)爬蟲不需要訪問數(shù)據(jù)庫,自動抓取頁面信息的特性,對程序設(shè)計資源庫的建設(shè)進(jìn)行探索和實踐[1]。通過對目標(biāo)網(wǎng)站的分析和爬取,實現(xiàn)資源聚合,完成資源庫在內(nèi)容上從無到有的突破。通過對當(dāng)下流行的一些技術(shù)進(jìn)行實際的開發(fā)和應(yīng)用,為以后構(gòu)建功能更加完善的資源庫系統(tǒng)提供非常有用的實踐經(jīng)驗。同時,本文雖然是針對程序設(shè)計課程資源庫建設(shè)開展研究,但研究方法考慮通用性,只需通過主題庫和爬取規(guī)則更新,就可以適用于其他課程的資源建設(shè)中。
二、系統(tǒng)總體架構(gòu)
本系統(tǒng)被設(shè)計為三個模塊。分別為:爬蟲模塊,API模塊和數(shù)據(jù)可視化模塊,系統(tǒng)架構(gòu)如圖1所示。
本系統(tǒng)通過爬取特定的URL,下載其標(biāo)識的資源頁面,從互聯(lián)網(wǎng)中獲取所需的信息。并在爬蟲模塊中借用Redis進(jìn)行信息文本的清洗、組合、判重等操作。最后將合格的資源存入MongoDB數(shù)據(jù)庫中,API則根據(jù)數(shù)據(jù)可視化的要求,通過對MongoDB數(shù)據(jù)庫中的已存信息進(jìn)行查詢等操作,實現(xiàn)對應(yīng)API功能[2]。數(shù)據(jù)可視化模塊則同過調(diào)用API獲取數(shù)據(jù),在瀏覽器中對數(shù)據(jù)進(jìn)行加工和展示,使師生用戶可以無障礙使用本系統(tǒng)。
三、爬蟲模塊設(shè)計
爬蟲模塊在Scrapy和Scrapy-redis組件的基礎(chǔ)上,進(jìn)行功能拓展和實現(xiàn)。又分為多個子模塊,包括:控制子模塊,url重復(fù)過濾模塊,頁面解析模塊,文本相似過濾模塊,存儲模塊[3]。整個模塊結(jié)構(gòu)如圖2所示。
(一)控制子模塊
本模塊是在Scrapy-Redis組件中所實現(xiàn)的調(diào)度器、爬蟲等類的基礎(chǔ)上,通過定義重載一些方法實現(xiàn)對爬蟲的個性化控制[4]。其控制流程如圖3所示。
爬蟲啟動后,會首先運行spider類中的start_requests方法,在該方法中,我們進(jìn)行主從模式的判斷,如果是主模式,則要進(jìn)一步判斷是否已有Cookies,如果沒有,則需要同過Selenium模擬瀏覽器登錄目標(biāo)網(wǎng)站獲取Cookies,并將Cookies存儲于Redis中,共享給從模式啟動的爬蟲使用。Cookies生成之后,主模式下會生成待爬取的初始請求隊列,然后進(jìn)入頁面的爬取解析循環(huán)。對于從模式啟動的爬蟲,則直接進(jìn)入頁面的爬取解析循環(huán),如果沒有待爬取的請求,則等待。經(jīng)過頁面解析之后,將提取后的結(jié)構(gòu)化數(shù)據(jù)通過存儲子模塊進(jìn)行存儲。其中,對于新產(chǎn)生的URL和新提取的數(shù)據(jù)都要經(jīng)過重復(fù)過濾,合格的URL和數(shù)據(jù)才能進(jìn)入下一步流程當(dāng)中[5]。
(二)URL重復(fù)過濾模塊
該模塊主要實現(xiàn)了Bloom Filter算法,并把它與實際爬蟲應(yīng)用結(jié)合起來。將Scrapy-redis原有的利用Redis集合特性的去重模塊進(jìn)行替換。算法和調(diào)用接口的具體實現(xiàn)主要在DBloomFilter類中完成,該類類圖如圖4所示。
其中,SEEDS屬性是Bloom Filter算法所需要的哈希函數(shù)的隨機(jī)種子。m是位數(shù)組的位數(shù),k是哈希函數(shù)的個數(shù),conn是Redis連接的實例,key是Redis中存儲位數(shù)組的鍵名,由于Redis中最大只支持512M的位數(shù)組,為了在海量數(shù)據(jù)下依然能保證較高的正確率,將超過512M大小的位數(shù)組進(jìn)行分塊處理,mem屬性是512M分塊的個數(shù),blocknum是每個分塊的編號[6]。
init方法初始化Bloom Filter所需的各種參數(shù)m,k,conn 等。
getHashs則是對傳進(jìn)來的參數(shù)使用k個不同的哈希函數(shù),獲得k個哈希值,即該URL在位數(shù)組中的位置。
isExist方法是提供給爬蟲判斷URL是否已經(jīng)爬取了的方法,接受需要去重的數(shù)據(jù)作為參數(shù),調(diào)用getHashs方法獲得URL的k個哈希值,并判斷位數(shù)組中是否已經(jīng)存在。存在返回True,不存在返回False。
add方法是提供給其他模塊向位數(shù)組中加入該URL記錄的方法。
(三)頁面解析模塊
頁面解析模塊主要是對Spider類的拓展和實現(xiàn)。類圖如圖5所示。
頁面解析模塊主要是兩個解析方法,listParse方法主要解析爬取來的列表頁面。根據(jù)列表頁中的資源id再進(jìn)行構(gòu)造對應(yīng)資源的URL。problemParse則是對具體資源頁面的解析,通過Scrapy提供Item解決方案,提取組合成結(jié)構(gòu)化的數(shù)據(jù),暫時組織在Item類的實例中。
(四)文本相似過濾模塊
該模塊是基于Scapy提供的Item pipelies組件機(jī)制實現(xiàn)的。通過編寫pipeline組件,并規(guī)定它的執(zhí)行順序,實現(xiàn)對頁面解析模塊獲得的結(jié)構(gòu)化數(shù)據(jù)進(jìn)行詳細(xì)過濾[7]。頁面解析模塊最終生成包含數(shù)據(jù)的Item實例,并把它轉(zhuǎn)交這Item pipeline中,pipeline組件有序地對Item進(jìn)行處理。
DDupefilterPipeline是實現(xiàn)的組件類。當(dāng)Item通過時,它調(diào)用Simhash類提供的方法,對Item中的特定字段進(jìn)行相似度判別。對于擁有和已經(jīng)入庫的數(shù)據(jù)較高相似度的Item將被丟棄。只有相似度合格的Item才能進(jìn)入下一個pipeline組件中。
SimHash類是實現(xiàn)SimHash算法的工具類。它的類圖如圖6所示。
該類的兩個屬性會在初始化時賦值,hashBitNum是生成的哈希值的長度。maxKeywordWeight是關(guān)鍵詞權(quán)重值的最大值[8]。
simHash方法通過調(diào)用jieba分詞的分詞方法,對文本content進(jìn)行分詞,并從中提取帶有權(quán)重值的關(guān)鍵詞列表,把得到的列表交給hashFeature方法。在hashFeature方法中,實現(xiàn)了SimHash算法里所講的流程,最終得到了該文本的SimHash值。
is_equal方法是用來判斷兩個文本的相似度的,通過調(diào)用hmDistance方法,得到兩個SimHash值的漢明距離,來判斷相似度是否超過給定的上限。如果超過則返回True,否則返回False。
hashFunc和tokenizerFunc方法則是算法需要的哈希函數(shù)方法和分詞方法[9]。
在具體去重中,DDupefilterPipeline類的process_item方法會先調(diào)用simHash方法,獲取Item中給定字段的SimHash值。判斷這個值是否已經(jīng)在Redis數(shù)據(jù)庫中,如果不存在則調(diào)用is_equal方法,與Redis數(shù)據(jù)庫中的每一個SimHash進(jìn)行對比,相似度高于上限的直接丟棄,相似度合格的則把該SimHash值存入Redis中,并將該Iten傳入下一個pipeline組件中。
(五)存儲子模塊
和文本相似過濾模塊相似,存儲子模塊通過pipeline組件,對經(jīng)過去重的Item進(jìn)行存儲操作。DMongodbPipeline類通過調(diào)用pymongo提供的API接口,完成對MongoDB的連接等操作。完成對有效數(shù)據(jù)的插入。
由于MongoDB是非關(guān)系型數(shù)據(jù)庫,和傳統(tǒng)的關(guān)系型數(shù)據(jù)庫相比,它是以BSON文檔作為基本的數(shù)據(jù)模型,沒有表的概念。在MongoDB中,一個數(shù)據(jù)庫可以包含多個集合,一個集合包含了同類文檔,文檔中又可以嵌套文檔、數(shù)組和文檔數(shù)組[10]。
在本系統(tǒng)中MongoDB數(shù)據(jù)庫主要有兩個集合:problems和knowledgePoints。
四、API模塊
API模塊使用Koa2.js框架進(jìn)行開發(fā),為數(shù)據(jù)可視化模塊提供獲取數(shù)據(jù)的API接口。它的主要功能就是接收客戶端應(yīng)用發(fā)來的http請求,從中提取有效安全的參數(shù),在數(shù)據(jù)庫中完成數(shù)據(jù)的查詢,并將數(shù)據(jù)返回給客戶端應(yīng)用。
Koa2.js框架是基于NodeJS平臺的下一代Web開發(fā)框架,是由 Express 原班人馬打造的,致力于成為一個更小、更富有表現(xiàn)力、更健壯的 Web 框架。 使用JavaScript編寫應(yīng)用時,會面臨重復(fù)煩瑣的“回調(diào)地獄”問題。在Koa2中通過組合不同的 generator,可以避免這一問題,并極大地提升錯誤處理的效率。Koa2為了保證自身的簡潔性,自身內(nèi)核除了關(guān)鍵內(nèi)容以外,把路由、解析等功能都被用中間件的形式來實現(xiàn),它僅僅提供了一個輕量優(yōu)雅的函數(shù)庫,使開發(fā)者在編寫 Web 應(yīng)用更加得心應(yīng)手。
整個流程看起來很像洋蔥,但并不是一層一層地執(zhí)行,而是以中間件調(diào)用next方法的地方為界,當(dāng)請求Request傳來時,先一次執(zhí)行每個中間件next之前的部分,當(dāng)下一層中間件執(zhí)行完后,再執(zhí)行本層next后的部分[11]。
通過在koa-router中間件中定義API路由,并指定匹配到該路由時的應(yīng)該執(zhí)行的回調(diào)函數(shù)。在回調(diào)函數(shù)中進(jìn)行數(shù)據(jù)庫查詢,并對該請求進(jìn)行響應(yīng),返回數(shù)據(jù)。所有的回調(diào)函數(shù)按功能被組織在特定的Controller類中。
ProblemController類主要完成了目前階段所有API的回調(diào)函數(shù)的定義和實現(xiàn)。其類圖如圖7所示。
getProblemByType方法中實現(xiàn)了按條件對數(shù)據(jù)庫進(jìn)行檢索,并利用MongoDB的skip、limit、sort等方法以及_id的特性,實現(xiàn)了分頁查詢,比單獨使用skip和limit方法實現(xiàn)分頁有了更好的性能,尤其是數(shù)據(jù)量龐大時。getKnowledgePoints則是返回了當(dāng)前知識點的子知識點。
五、系統(tǒng)測試
關(guān)于爬取速度方面,經(jīng)測試,在單機(jī)條件下運行,爬蟲持續(xù)運行無報錯,穩(wěn)定持續(xù)爬取數(shù)據(jù)。90分鐘入庫數(shù)據(jù)3140條,平均35條/min。
在爬取完整性方面,針對某網(wǎng)站最終需要爬取5835個頁面,共爬取5835個頁面,實現(xiàn)全部爬取無遺漏。最終數(shù)據(jù)庫有4886條數(shù)據(jù),有949條數(shù)據(jù)被判定相似或重復(fù)。
針對相似度過濾方面,經(jīng)測試爬蟲系統(tǒng)的log信息提示丟棄掉了約5%和已入庫文本相似度極高的文本,經(jīng)過系統(tǒng)比對規(guī)則確認(rèn),這部分確實屬于重復(fù)資源,系統(tǒng)予以舍棄,不做重復(fù)入庫。當(dāng)數(shù)據(jù)庫中存入了多條相似,但要求實現(xiàn)不同函數(shù)的問題,證明文本相似過濾模塊運行性能在預(yù)期內(nèi),沒有出現(xiàn)不能容忍的高誤判率。
六、總結(jié)
本文采用了穩(wěn)定性及拓展性良好的Scrapy/Scrapy-redis框架,實現(xiàn)對數(shù)據(jù)的清洗,去重以及入庫等操作。運用Downloader Middleware機(jī)制對發(fā)出的爬取請求進(jìn)行定制,同時對服務(wù)器的響應(yīng)進(jìn)行識別,對不同的響應(yīng)狀態(tài)碼進(jìn)行不同的處理。為了實現(xiàn)分布式爬取而采取的Redis數(shù)據(jù)庫操作的原子性和基于內(nèi)存的特性發(fā)揮了極大的性能優(yōu)勢。經(jīng)測試,資源庫系統(tǒng)各方面表現(xiàn)穩(wěn)定,擁有良好的可拓展性,滿足設(shè)計需求。
值得進(jìn)一步探索改進(jìn)之處主要表現(xiàn)在,目標(biāo)網(wǎng)站的反爬機(jī)制對爬蟲系統(tǒng)有一定限制。目標(biāo)網(wǎng)站為限制同一IP在短時間內(nèi)的請求數(shù),為了保證爬取的準(zhǔn)確度,爬蟲不得不進(jìn)行自我休眠,限制了爬取速度??梢酝ㄟ^增加機(jī)器、選用優(yōu)秀穩(wěn)定的代理池去解決。
[ 參 考 文 獻(xiàn) ]
[1] 陳永彬. 基于聚焦爬蟲技術(shù)的教學(xué)資源搜集與自動整理方法研究[D]. 東北師范大學(xué),2011.
[2] 陳昭穩(wěn). 基于網(wǎng)絡(luò)爬蟲軟件建設(shè)主題網(wǎng)絡(luò)信息資源庫的研究——以高鐵網(wǎng)絡(luò)信息資源庫建設(shè)為例[J]. 安徽電子信息職業(yè)技術(shù)學(xué)院學(xué)報,2014(6):12-14.
[3] 郭小丹. 幾種開源網(wǎng)絡(luò)爬蟲功能比較[J]. 黑龍江科技信息,2015(25):154.
[4] 劉建明. 垂直搜索引擎中的主題爬蟲技術(shù)研究[D].廣東工業(yè)大學(xué),2013.
[5] 金斯特. 基于Web 挖掘的主題搜索引擎網(wǎng)頁抓取策略的研究[D]. 浙江工業(yè)大學(xué),2014.
[6] Yuhao Fan. Design and Implementation of Distributed Craw-ler System Based on Scrapy[J]. IOP Conference Series:Ea-rth and Environmental Science,2018,108(4).
[7] Luo L, Guo D, Ma R T B, et al. Optimizing Bloom Filter: Challenges, Solutions, and Comparisons[J]. arXiv:1804.04777v2[CS.DS] 7 Jan 2019:10-32.
[8] Manku G S,Jain A,Sarma A D. Detecting near-duplicates for web crawling[C] International Conference on World W-ide Web. ACM,2007:141-150.
[9] Jain A, Manku G S. Near-duplicate document detection for web crawling: US,US8140505[P]. 2012.
[10] Haber,Itamar. MongoDB and Redis pair volume with velocity[J]. InfoWorld.com,2015.
[11] 程桂花,沈煒,何松林,等. Node.js中Express框架路由機(jī)制的研究[J]. 工業(yè)控制計算機(jī),2016(8):101-102.
[責(zé)任編輯:黃緊德]