高文超 李浩源 徐永康
摘要:隨著信息量的增多,為用戶提供便捷的搜索服務也更加具有挑戰(zhàn)性。大規(guī)模存儲信息并精確搜索的代價是巨大的,人們需要在信息搜索的快捷性與成本中找到平衡。系統(tǒng)實現(xiàn)一個基于網(wǎng)絡爬蟲的搜索引擎。軟件結構分為爬蟲部分,數(shù)據(jù)庫部分,前端顯示部分。同時,描述了擴展成分布式爬蟲的方法。硬件方面需要多臺主機,軟件方面包括Scrapy爬蟲、數(shù)據(jù)庫、Django框架。最終設計并實現(xiàn)了一個具有良好的健壯性和擴展性的網(wǎng)絡爬蟲系統(tǒng)。
關鍵詞:爬蟲;信息;搜索引擎;數(shù)據(jù)庫;Web框架
中圖分類號:TP393? ? ? 文獻標識碼:A
文章編號:1009-3044(2020)30-0006-04
Abstract: In the Internet era, with an increasing amount of information, it is more challenging to provide users with convenient search services. The cost of storing information on a large scale and searching accurately is huge, and people need to balance the speed and cost of information searching. This system implements a search engine based on a web crawler. The software structures are divided into the crawler part, database part, and front-end display part. At the same time, it describes the method to expand into a distributed crawler. In terms of hardware, multiple hosts are needed. In terms of software, Scrapy crawlers, databases, and the Django framework. Finally, a web crawler system with good robustness and expansibility is designed and implemented.
Key words: Reptile; information; Search Engines; database; web framework
1 背景
身處于信息時代,數(shù)據(jù)共享與查詢越來越便捷,基于數(shù)據(jù)的服務也越來越多,各行各業(yè)越來越依賴于爬蟲對數(shù)據(jù)進行提取[1]。但是,隨著信息數(shù)據(jù)量迅速增長,這些數(shù)據(jù)中包含著許多模糊不清的信息,構成了一個龐大的網(wǎng)絡資源庫。因此人們需要從海量數(shù)據(jù)中提取所需要的信息,同時平衡成本。爬蟲能夠將用戶所需要的數(shù)據(jù)提取出來,但是僅僅依靠單機爬蟲,采集速度難以處理繁多的頁面,而硬件的發(fā)展也無法跟上信息量的增長。因此,合理限定抓取范圍,開發(fā)面向與各個領域的輕量化搜索引擎,擴展單機爬蟲為分布式爬蟲都是可行的解決方法。
2 總體設計與功能
2.1 功能設計
一個單詞在不同領域具有不同含義,用戶直接在通用搜索引擎上搜索可能會顯示完全不同的結果。需要精細化搜索引擎范圍,本系統(tǒng)開發(fā)一套面向于某一領域和中小企業(yè)的搜索引擎,具有數(shù)據(jù)范圍相對較集中,數(shù)據(jù)量相對較小的特點。
通過對需求的分析,將該搜索引擎分為兩個頁面。其一是搜索網(wǎng)站搜索主頁,包括搜索分類選擇、輸入框輸入信息并搜索、熱門搜索與搜索記錄共同組成了搜索門戶方便用戶搜索,其二是搜索網(wǎng)站結果顯示頁,在該頁面上顯示搜索的相關信息,搜索輸入框,滿足用戶信息瀏覽和繼續(xù)搜索的需求。第一部分,將搜索的信息分為幾個板塊,用戶可以選擇不同板塊來進行對應的搜索。第二部分,在頁面上顯示熱門搜索和歷史記錄,用戶可以點擊對應的關鍵字進入對應的結果頁鏈接。在顯示搜索結果的時候,顯示搜索標題、簡介、結果數(shù)據(jù)統(tǒng)計信息等,方便用戶瀏覽。
2.2 模型設計
本系統(tǒng)采用B/S架構,服務器作為核心事物的重要部分[2]。后端框架選用Django搭建,前端頁面通過嵌入來顯示網(wǎng)頁,并在Django框架中設置數(shù)據(jù)處理函數(shù)處理數(shù)據(jù)庫中的信息。
本系統(tǒng)設計針對某領域提供信息,不同用戶搜索的內(nèi)容可能有不同的爬蟲爬取,相同的搜索領域由同類型的爬蟲抓取數(shù)據(jù)。所有抓取的數(shù)據(jù)信息根據(jù)不同數(shù)據(jù)庫的特點分別保存。
作為一個系統(tǒng),穩(wěn)定是最重要的因素,因此需要考慮穩(wěn)定運行,數(shù)據(jù)備份等因素,此外需要具有良好的可拓展性,能夠隨著用戶增長的需求來擴充數(shù)據(jù)的范圍,因此代碼的編寫需要規(guī)范化,方便后期維護升級。
本系統(tǒng)分為三部分,包括爬蟲部分,存儲部分和顯示部分。各部分功能與主要技術設計如圖1所示:
1)爬蟲部分:該模塊用于爬取目標網(wǎng)站信息,包括實現(xiàn)自動登錄,設置措施突破反爬限制,設置網(wǎng)頁爬取策略根據(jù)不同網(wǎng)站特點爬取對應信息,數(shù)據(jù)字段提取與保存信息等功能。
2)存儲部分:該模塊的功能是將爬蟲爬取的信息分別存儲到不同的數(shù)據(jù)庫中。MySQL數(shù)據(jù)庫用來存儲單機上爬取的信息,并作為備份。Elasticsearch數(shù)據(jù)庫用于匯總存儲數(shù)據(jù)并構建索引。Redis數(shù)據(jù)庫是內(nèi)存數(shù)據(jù)庫,存取數(shù)據(jù)十分迅速,用于保存常用信息,同時作為分布式爬蟲隊列管理工具。
3)顯示部分:本模塊設置服務端處理數(shù)據(jù)的過程,使用基于Python的Django框架。選擇B/S架構,同時將處理后的數(shù)據(jù)在瀏覽器頁面上顯示。后端框架選取MVT模式。
3 詳細實現(xiàn)
3.1 爬蟲的實現(xiàn)
1)爬蟲規(guī)則設計
本系統(tǒng)實現(xiàn)的爬蟲基于Scrapy框架,在爬蟲模塊中主要完成爬取目標網(wǎng)站的功能。根據(jù)不同網(wǎng)站的結構,選取深度優(yōu)先策略和廣度優(yōu)先策略[3]。設計信息解析模塊,對目標網(wǎng)站的布局與邏輯進行分析,發(fā)現(xiàn)網(wǎng)站網(wǎng)頁結構主要可以分為主頁、列表頁、詳情頁。網(wǎng)站的主頁設為網(wǎng)站的一級頁面,是用戶進入網(wǎng)站的入口。所有內(nèi)部頁面可以通過主頁上的鏈接進行訪問。網(wǎng)站的列表頁是二級頁面,負責網(wǎng)站某一分類下的所有相關頁面的URL信息。詳情頁定義為三級頁面,是用戶訪問該網(wǎng)站的目標頁面,同時也是爬蟲主要抓取對象和信息提取頁。整個過程如圖2。
2)數(shù)據(jù)處理模塊
首先定義爬蟲名稱,爬取的域名和起始頁面。其次,獲取網(wǎng)頁列表頁URL,下載后使用parse函數(shù)處理,同時定理next_url來循環(huán)爬取其他URL。然后在詳情頁面上具有大部分的目標信息,針對這些信息,使用CSS和XPATH選擇器提取頁面詳細信息。部分字段提取樣式如表1:
①動態(tài)頁面加載:部分網(wǎng)頁并不會一次性顯示全部數(shù)據(jù)信息,需要通過鼠標下滑或者點擊對應按鈕才能夠查看并顯示更多內(nèi)容。編寫process_request函數(shù),調(diào)用browser.execute_script方法控制網(wǎng)頁下滑來進行動態(tài)網(wǎng)頁解析。
②存儲部分:爬蟲在一段時間內(nèi)訪問網(wǎng)站次數(shù)過多,其IP地址會被網(wǎng)站識別重定向或封禁。使用IP代理池隨機更換IP地址防止網(wǎng)站識別[4]。定義GetIP類來實現(xiàn)對IP地址的控制,此類包含兩個函數(shù),delete_ip(self,ip)用來從數(shù)據(jù)庫中刪除無效IP。judge_ip(self,ip,port)用來判斷IP是否可用。
③模擬登錄的設計:部分網(wǎng)站需要進行登錄才能訪問網(wǎng)站信息,同時登錄過程中可能會需要輸入驗證碼。對于針對這一部分網(wǎng)站,首先在CMD中啟動遠程調(diào)試打開瀏覽器防止識別出WebDriver。加載瀏覽器驅動啟動瀏覽器。最大化界面并定位輸入框與按鈕,在登錄界面使用選擇器定位登陸元素和查找用戶名密碼輸入框,使用Selenium自動輸入預設信息并登錄[5]。最后,如果在網(wǎng)頁上找到對應信息則判斷登陸成功。具體登錄流程如下:
4)分布式爬蟲改進方案
本系統(tǒng)采用主從結構,包含一個控制節(jié)點和一個爬行節(jié)點具體方法如下:
①安裝依賴包,例如Scrapy和Scrapy-Redis等。
②構建分布式爬蟲系統(tǒng)。增加dupefilter.py文件實現(xiàn)去重,替換Scheduler調(diào)度器。
③修改Spider組件,指定Redis_Key并在Spider繼承動態(tài)網(wǎng)頁加載功能。
④修改配置文件,添加數(shù)據(jù)連接功能,配置本機端口和地址。修改Pipeline.py在ITEM_PIPELINES中添加scrapy_redis.pipelines.RedisPipeline,將爬取的信息存入Redis 數(shù)據(jù)庫。
⑤集成BloomFilter過濾器,在大型爬蟲中用于URL去重[7]。本系統(tǒng)中過濾器通過add函數(shù)添加元素,is_exist函數(shù)查詢,get_hashs函數(shù)用來取得哈希值。
3.2 數(shù)據(jù)庫的實現(xiàn)
1)數(shù)據(jù)庫總體設計
部分本系統(tǒng)數(shù)據(jù)庫分為三種,MySQL數(shù)據(jù)庫負責單機爬蟲數(shù)據(jù)的備份。Redis內(nèi)存數(shù)據(jù)庫負責保存與修改常用數(shù)據(jù)。Elasticsearch數(shù)據(jù)庫負責人構建索引,支持搜索引擎功能。三種數(shù)據(jù)庫共同構成本項目的數(shù)據(jù)庫模塊。
2)數(shù)據(jù)庫表的設計
以某網(wǎng)站新聞板塊為例,通過分析爬取目標來設置數(shù)據(jù)庫的字段。同時實現(xiàn)數(shù)據(jù)存儲的安全性,設置Mysql Twisted Pipeline使用異步入庫方式。以新聞模塊為例,數(shù)據(jù)庫表如下所示:
3)ES數(shù)據(jù)庫建立
①在數(shù)據(jù)庫中,定義數(shù)據(jù)庫的名稱,分片數(shù)量[8]。然后建立索引,通過Mappings函數(shù)將輸入數(shù)據(jù)轉變成可以搜索到的索引項,通過Kibana調(diào)試。
②建立索引與映射,在工程中的Models包里的es_type.py來建立的,它可以用來控制數(shù)據(jù)向ES的寫入。設置Meta信息。在其中定義這些數(shù)據(jù)存儲的索引index名并設置文檔類型doc_type方便前端網(wǎng)頁分類。在pipelines.py中定義ElasticsearchPipeline類將數(shù)據(jù)寫入ES中。在這個類下定義process_item函數(shù)實現(xiàn)將item類轉換為ES數(shù)據(jù)。
4)Redis數(shù)據(jù)庫建立
為了加快對常用數(shù)據(jù)的存取速度,本系統(tǒng)將統(tǒng)計各網(wǎng)站爬取頁面的計數(shù)器存入Redis數(shù)據(jù)庫中。在Scrapy框架中Redis數(shù)據(jù)庫的主要工作是統(tǒng)計網(wǎng)頁總數(shù)。在items.py文件中設置,在每次往ES存入一個數(shù)據(jù)的時候,使用redis_cli函數(shù)中incr方法,對不同類型的文章存儲時進行計數(shù),使得Redis中存儲了每種類型文章的數(shù)量。
對于Scrapy-Redis框架,修改對應的措施,實現(xiàn)分布式爬蟲的要求。首先在Scrapy-Redis功能配置的defaults文件中設置REDIS_CLS=redis.StrictRedis可以提供對Redis集群操作的方法。然后添加Redis配置,對DOWNLOADER_MIDDLEWARES,SCHEDULER和ITEM_PIPELEINES分別設置對應的措施滿足分布式爬蟲的要求。最后在connection中添加Redis集群實例化的措施。
3.3 服務端的實現(xiàn)
本系統(tǒng)中,服務端作為關鍵模塊之一,負責對輸入文本進行處理,與數(shù)據(jù)庫進行交互,處理數(shù)據(jù)并返回結果到前端頁面上。主要流程如下:
1)導入靜態(tài)頁面,搭建兩個靜態(tài)頁面模板,命名為index和result放入新建工程的templates文件夾下,將圖片資源放入static文件夾。在urlpatterns中配置靜態(tài)頁面的路徑。
2)實現(xiàn)搜索推薦功能。在index頁面完成搜索建議函數(shù),使用get方法獲取輸入文本,與搜索類型s.type共同組成請求。在視圖中定義SearchSuggest類在類中處理文本,后端根據(jù)輸入內(nèi)容匹配補全字段。
3)搜索結果顯示。在view.py定義SearchView類,將后臺信息傳遞給前端,取得關鍵詞匹配高亮處理,設置每頁顯示結果數(shù)。并將數(shù)據(jù)庫中主要信息傳給前端頁面對應位置顯示。
4)搜索記錄與熱門搜索顯示。定義add_search函數(shù)存儲搜索數(shù)據(jù),把數(shù)組存儲到瀏覽器本地。統(tǒng)計搜索次數(shù)并按照時間順序顯示歷史記錄。熱門搜索需要調(diào)用Redis數(shù)據(jù)庫中的sortedSet集合,通過ZINCRBY命令實現(xiàn)搜索數(shù)量記錄。最后返回高頻搜索關鍵字。
4 系統(tǒng)結果展示
4.1 開發(fā)環(huán)境的展示
本系統(tǒng)中,主要工具的版本號如下表所示:
4.2 門戶起始頁展示
用戶進入搜索引擎起始頁面index.html,可以選擇搜索模塊,并在搜索框中輸入文本,文本內(nèi)容每次變化則會觸發(fā)一次搜索,在數(shù)據(jù)庫中查找匹配項并顯示。也可以瀏覽并點擊熱門搜索和搜索記錄中的關鍵詞。
4.3 搜索結果頁展示
點擊搜索按鈕之后網(wǎng)站轉到結果顯示界面result.html。信息按照相關度得分排序,同時將匹配字符標紅。
點擊搜索按鈕之后網(wǎng)站轉到結果顯示界面。信息按照相關度得分排序,將匹配字符標紅。同時顯示網(wǎng)站數(shù)量和搜索附加信息。
4.4 后臺數(shù)據(jù)展示
MySQL數(shù)據(jù)庫保存各臺主機爬取信息,作為備份保存數(shù)據(jù)。以職位網(wǎng)站為例,單機抓取有效網(wǎng)頁數(shù)量600余條,本系統(tǒng)隨機抓取延遲時間范圍5-15秒。理論上每小時可抓取360個網(wǎng)頁,2小時可抓取720個網(wǎng)頁。但由于網(wǎng)絡帶寬和隨機延遲,導致抓取數(shù)量減少。存儲數(shù)據(jù)如下所示:
5 總結與展示
本文主要實現(xiàn)基于Scrapy網(wǎng)絡爬蟲的搜索引擎。該系統(tǒng)可滿足中小企業(yè)或某一領域范圍內(nèi)的搜索需求。本系統(tǒng)具有擴展性強、穩(wěn)定性高等特點。但是,本系統(tǒng)在單機上搭建了分布式爬蟲,并未考慮實際中不同服務器節(jié)點性能存在差異等問題,同時針對部分網(wǎng)站,應該基礎研究設置更加合理的爬取策略,降低網(wǎng)站反爬偵測的概率,提升系統(tǒng)的性能。
參考文獻:
[1] 樊宇豪.基于Scrapy的分布式網(wǎng)絡爬蟲系統(tǒng)設計與實現(xiàn)[D].成都:電子科技大學,2018.
[2] 王貴智.基于B/S智慧教務綜合管理系統(tǒng)的設計與實現(xiàn)[D].長沙:湖南大學,2019.
[3] 王芳,張睿,宮海瑞.基于Scrapy框架的分布式爬蟲設計與實現(xiàn)[J].信息技術,2019,43(3):96-101.
[4] 余豪士,匡芳君.基于Python的反爬蟲技術分析與應用[J].智能計算機與應用,2018,8(4):112-115.
[5] 馮興利,洪丹丹,羅軍鋒,等.基于Selenium+Python的高校統(tǒng)一身份認證自動化驗收測試技術研究[J].現(xiàn)代電子技術,2019,42(22):89-91,97.
[6] 梁浩喆,馬進,陳秀真,等.現(xiàn)代瀏覽器中Cookie同源策略測試框架的設計與實現(xiàn)[J].通信技術,2019,52(12):3039-3045.
[7] 孟慧君.基于Bloom Filter算法的URL去重算法研究及其應用[D].開封:河南大學,2019.
[8] 王磊,王胤然,徐寅,等.一種ElasticSearch分片擴展方法:CN108509438A[P].2018-09-07.
【通聯(lián)編輯:謝媛媛】