霍英 李小帆 丘志敏 李彥廷
關(guān)鍵詞:大數(shù)據(jù);數(shù)據(jù)采集;網(wǎng)絡(luò)爬蟲
中圖分類號:TP319 文獻(xiàn)標(biāo)識碼:A
1引言(Introduction)
數(shù)據(jù)對企業(yè)經(jīng)營、政府決策、社會動態(tài)分析等起著極其重要的作用,如何大規(guī)模、快速地采集數(shù)據(jù)已成為有效提取數(shù)據(jù)價值的先決條件,數(shù)據(jù)采集的效率直接決定了數(shù)據(jù)的有效性和及時性。在大數(shù)據(jù)時代背景下,如何從大數(shù)據(jù)中采集有用的信息是大數(shù)據(jù)分析至關(guān)重要的一個環(huán)節(jié),也是大數(shù)據(jù)分析的入口[1]。
對于大多數(shù)用戶提出的與主題或領(lǐng)域相關(guān)的查詢需求,傳統(tǒng)的搜索引擎得到的結(jié)果往往不盡如人意,為了克服傳統(tǒng)的搜索引擎的不足,提高抓取資源的質(zhì)量,面向主題的爬蟲即聚焦爬蟲應(yīng)運(yùn)而生,并且迅速成為爬蟲研究的熱點之一。隨著動態(tài)網(wǎng)頁技術(shù)的發(fā)展,網(wǎng)絡(luò)爬蟲遇到越來越多的困難,很多動態(tài)網(wǎng)頁根本無法搜索到[2],例如聊天室系統(tǒng)等,還有許多頁面必須登錄才可以查看,因此產(chǎn)生了智能爬蟲。但是,隨著人工智能、大數(shù)據(jù)挖掘等行業(yè)的興起,普通的單機(jī)版爬蟲已不能滿足行業(yè)發(fā)展的要求,因此又產(chǎn)生了分布式爬蟲,如分布式爬蟲框架SeimiCrawler、WebCollector、Scrapy等[3],相應(yīng)也產(chǎn)生了大量爬蟲企業(yè)和軟件,如深圳數(shù)闊信息技術(shù)有限公司的八爪魚數(shù)據(jù)采集器、杭州云微數(shù)據(jù)信息有限公司的云微大數(shù)據(jù)、北京宏博知微科技有限公司的知微事件、北京微指數(shù)科技有限公司的微指數(shù)等。
本文在微博大數(shù)據(jù)環(huán)境下,以輿情數(shù)據(jù)采集、用戶行為分析為應(yīng)用背景,提出了一種爬蟲數(shù)據(jù)采集系統(tǒng)的設(shè)計與實現(xiàn)方案。該方案主要采用的是聚焦爬蟲和增量式爬蟲相結(jié)合,同時基于內(nèi)容評價的爬行策略,對用戶給定的關(guān)鍵詞進(jìn)行搜索,并在其發(fā)生變化時對相關(guān)的內(nèi)容進(jìn)行更新,從而實現(xiàn)數(shù)據(jù)采集的及時性和有效性。
2 網(wǎng)絡(luò)數(shù)據(jù)采集技術(shù)(Network data collectiontechnology)
網(wǎng)絡(luò)數(shù)據(jù)采集是指通過網(wǎng)絡(luò)爬蟲或網(wǎng)站公開API(Application Programming Interface,應(yīng)用程序編程接口)等方式從網(wǎng)站上獲取數(shù)據(jù)信息,該方法可以將非結(jié)構(gòu)化數(shù)據(jù)從網(wǎng)頁中抽取出來,將其存儲為統(tǒng)一的本地數(shù)據(jù)文件,并以結(jié)構(gòu)化的方式存儲。
2.1網(wǎng)絡(luò)爬蟲技術(shù)簡介
網(wǎng)絡(luò)爬蟲[ 4 ]又稱為網(wǎng)頁蜘蛛、網(wǎng)絡(luò)機(jī)器人, 在FOAF(Friend-of-a-Friend,朋友的朋友)社區(qū)中被稱為網(wǎng)頁追逐者,是一種按照某種規(guī)則,自動抓取互聯(lián)網(wǎng)上信息的程序或腳本;它是搜索引擎中最重要的組成模塊,是輿情采集系統(tǒng)中最核心的部分,也是數(shù)據(jù)分析工程師必須掌握的一種工具。爬蟲主要解決的問題有兩個:一是如何有效獲取網(wǎng)頁內(nèi)容。爬蟲在運(yùn)行過程中會遇到各種反爬策略,如限制訪問頻率、header頭部信息校驗、JavaScript動態(tài)生成頁面、IP限制、驗證碼限制、登錄限制等一系列技術(shù)。在解決上述問題的情況下,還必須思考如何在短時間內(nèi)獲得更多、更準(zhǔn)確的信息。除此之外,在數(shù)據(jù)獲取的過程中還有一系列需要遵守的協(xié)議,如robots.txt協(xié)議。二是如何對獲取到的網(wǎng)頁進(jìn)行數(shù)據(jù)的提取。網(wǎng)絡(luò)爬蟲首先根據(jù)搜索的目的建立待爬取URL隊列,并對這些URL所對應(yīng)的網(wǎng)頁進(jìn)行訪問,然后把從互聯(lián)網(wǎng)上抓取下來的資源進(jìn)行校驗,從提取的新URL中獲取數(shù)據(jù),直到URL隊列中的所有URL全部爬取完畢或滿足一定要求為止。
2.2聚焦網(wǎng)絡(luò)爬蟲
聚焦網(wǎng)絡(luò)爬蟲將爬取目標(biāo)定位在與主題相關(guān)的頁面中,主要應(yīng)用在對特定信息的爬取,并為某一類特定的人群提供服務(wù)[5]。聚焦網(wǎng)絡(luò)爬蟲的爬行策略分為基于內(nèi)容評價的爬行策略、基于鏈接評價的爬行策略、基于增強(qiáng)學(xué)習(xí)的爬行策略、基于語境圖的爬行策略。
2.3增量式網(wǎng)絡(luò)爬蟲
增量式更新指的是在更新的時候只更新改變的地方,未改變的地方則不更新,只爬取內(nèi)容發(fā)生變化的網(wǎng)頁或者新產(chǎn)生的網(wǎng)頁,能在一定程度上保證所爬取的網(wǎng)頁盡可能是新網(wǎng)頁。
本文給出的爬蟲數(shù)據(jù)采集系統(tǒng)主要采用的是聚焦網(wǎng)絡(luò)爬蟲和增量式網(wǎng)絡(luò)爬蟲相結(jié)合,同時基于內(nèi)容評價的爬行策略。
3數(shù)據(jù)采集系統(tǒng)設(shè)計(Design of data acquisitionsystem)
本文以輿情數(shù)據(jù)采集、用戶行為分析為應(yīng)用背景,因此系統(tǒng)主要是通過采集用戶指定話題的微博,并對數(shù)據(jù)進(jìn)行初步加工后,通過業(yè)務(wù)系統(tǒng)展示出來,能清晰直觀地體現(xiàn)某熱點話題的傳播速度,以及公眾對該事件的態(tài)度。系統(tǒng)處理流程如圖1所示。
3.1系統(tǒng)處理流程
從總體角度來看,微博輿情采集系統(tǒng)的主要工作流程如下:首先從微博采集數(shù)據(jù),在獲取數(shù)據(jù)后,對其進(jìn)行簡單的處理后[如數(shù)據(jù)結(jié)構(gòu)化、HTML(超文本標(biāo)記語言)標(biāo)簽剔除、時間格式化、去重等]存入原始數(shù)據(jù)庫,然后定時從原始數(shù)據(jù)庫中抽取數(shù)據(jù)并生成結(jié)論化數(shù)據(jù),寫入業(yè)務(wù)數(shù)據(jù)庫并通過Web頁面展示,讓用戶更加直觀地掌握微博上的輿情動態(tài)。
由于微博平臺有數(shù)以億計的用戶,每天發(fā)布的消息不計其數(shù),想要全部獲取不太可能,也沒有必要[6]。因此,數(shù)據(jù)采集過程是根據(jù)用戶輸入的關(guān)鍵字進(jìn)行采集,并且只把轉(zhuǎn)發(fā)評論達(dá)到一定數(shù)量(評論、點贊、轉(zhuǎn)發(fā)任意一項達(dá)到閾值以上)的博文存入業(yè)務(wù)數(shù)據(jù)庫即可。
3.2功能設(shè)計
數(shù)據(jù)采集系統(tǒng)主要是為后期業(yè)務(wù)數(shù)據(jù)分析與展示提供數(shù)據(jù)支持,由于需要經(jīng)常性修改,因此不需要太過復(fù)雜的交互功能,重點是提供基本的定時任務(wù)設(shè)置、日志分析、爬蟲監(jiān)控功能及爬蟲管理功能即可,其功能模塊如圖2所示。
設(shè)置定時任務(wù):用戶可自定義爬蟲任務(wù)計劃,系統(tǒng)默認(rèn)24 h不間斷地采集當(dāng)天數(shù)據(jù)。
日志分析:可查看爬蟲爬取的數(shù)據(jù)條目、爬取速度、頁面請求錯誤、開始運(yùn)行時間及最后一次請求頁面的時間等信息。
爬蟲狀態(tài)監(jiān)控:可查看各個節(jié)點的爬蟲運(yùn)行狀態(tài)。
爬蟲集群管理:可開始和終止任意一個節(jié)點的爬蟲。
3.3存儲設(shè)計
由于關(guān)系型數(shù)據(jù)庫插入性能較差且對存儲的數(shù)據(jù)格式有要求,故爬蟲爬取的數(shù)據(jù)將使用非關(guān)系型數(shù)據(jù)庫Mongodb存儲。Mongodb的格式靈活,插入性能高,數(shù)據(jù)之間沒有耦合性,容易水平擴(kuò)展,而且它不需要設(shè)計表結(jié)構(gòu),只需要指定相應(yīng)的集合即可,非常適合大數(shù)據(jù)爬取數(shù)據(jù)的存儲。
3.4搜索關(guān)鍵字功能設(shè)計
通過定時掃描業(yè)務(wù)數(shù)據(jù)庫中的關(guān)鍵字表,獲得關(guān)鍵字后,檢索用戶自定義的關(guān)鍵字映射文件,即存儲該關(guān)鍵字同義詞的文件。該文件需用戶自行維護(hù),并以“關(guān)鍵字.txt”的格式存儲在爬蟲所在的目錄下,若未定義則默認(rèn)使用該關(guān)鍵字。例如,“新冠.txt”文件中存儲了“新冠,冠狀病毒,新冠肺炎,肺炎,新型冠狀病毒肺炎,Covid 19”,則使用這六個詞進(jìn)行搜索,若未建立該文件,則將使用“新冠”進(jìn)行搜索,并根據(jù)其搜索返回的結(jié)果,進(jìn)行數(shù)據(jù)的采集和分類。
4數(shù)據(jù)采集系統(tǒng)實現(xiàn)(Implementation of dataacquisition system)
4.1技術(shù)方案
Scrapy是一個基于Python開發(fā)的Web抓取框架,通過它可以方便地從Web頁面上提取結(jié)構(gòu)化的數(shù)據(jù),常常被用于數(shù)據(jù)挖掘、監(jiān)測和自動化測試[7],它良好的擴(kuò)展性得到了大部分人的青睞,因為它是一個框架,所以任何人都可以根據(jù)需求修改它。
Scrapy提供了一個可通過簡單的JsonAPI(應(yīng)用程序接口)快速部署或控制爬蟲項目的軟件Scrapyd,然而其功能過于簡陋,并不能滿足大數(shù)據(jù)環(huán)境下實際應(yīng)用的需求,因此系統(tǒng)實現(xiàn)上借用了Github上的一個基于Scrapyd的開源項目ScrapydWeb,其良好的用戶交互界面,可輕松地實現(xiàn)管理本系統(tǒng)應(yīng)用的爬蟲項目,再在其基礎(chǔ)上安裝相應(yīng)的插件、實現(xiàn)相關(guān)代碼即可。
4.2對目標(biāo)網(wǎng)站信息進(jìn)行分析
要對網(wǎng)站數(shù)據(jù)進(jìn)行采集,需要先對相應(yīng)的頁面進(jìn)行分析,由于本系統(tǒng)是針對微博的數(shù)據(jù)進(jìn)行采集,為保證數(shù)據(jù)的完整性,本研究對微博的三個不同版本的頁面[8][桌面端、移動端(觸屏版)、移動端(weibo.cn)]分別進(jìn)行分析,并分別采集后再進(jìn)行數(shù)據(jù)合并。
4.2.1桌面端(s.weibo.com)頁面分析
Chrome等瀏覽器可以方便地查看頁面的信息以及請求/響應(yīng)信息,桌面端是微博三個版本中頁面最復(fù)雜、最難爬取的頁面,但是數(shù)據(jù)量是三個版本中最多的,高級查詢功能可以小時為單位查詢數(shù)據(jù)。
分析請求的URL(Uniform Resoure Locator,統(tǒng)一資源定位器)地址比對不同時間段不同頁面的URL地址如圖3所示,得出URL的生成規(guī)則為“https://s.weibo.com/weibo?q=搜索關(guān)鍵字&typeall=1&suball=1×cope=custom:xxxx-xxxx-x:xxxx-xx-xx-x&Refer=g&page=頁數(shù)”。
通過上文分析得出了URL的生成規(guī)則和響應(yīng)頁面格式,接下來可通過Xpath(XML Path Language,XML路徑語言)提取數(shù)據(jù)。分析頁面的HTML文件(圖4)
主要的Xpath表達(dá)式如下。
1. region=response.selector. xpath ( ' //span[@class="ctips"][2]/text()').extract()[0]
2. find_result=response.selector.xpath("http://div[@class='card card-no-result s-pt20b40']").extract()
3. cur_page=response.selector.xpath('//div[@class="m-page"]//li[@class="cur"]/a/@href').extract()[0][-6:]
4. page_urls=response.selector.xpath('//div[@class="m-page"]//li/a/@href').extract()
5. item['weibo_id']=card.xpath(".//@mid").extract()[0]
6. user_id=card.xpath(".//a[@class='name']/@href").extract()[0]
7. item['user_id']=re.split("\?",re.split("/",user_id)[-1])[0]
8. r.lpush("weibo_spider:start_urls","https://weibo.cn/{}/info".format(item['user_id']))
9. origin_weibo_user_id=header+card.xpath(".//a[@class='name']/@href").extract()[1]
10. item['origin_weibo_user_id']=re.split("/",origin_weibo_user_id)[-1]
11. names=card.xpath(".//a[@class='name']/@nick-name").extract()
12. urls=card.xpath(".//p[@class='from']/a[@target='_blank']/@href").extract()
13.item['create_at']=card.xpath( ".//p[@class='from']/a[@target='_blank'][1]/text()").extract()[0]
14. item['tool']=card.xpath(".//p[@class='from']/a[@rel='nofollow'][1]/text()").extract()[0]
15. i t e m [ ' c r e a t e _ a t ' ] = c a r d . x p a t h ( " . / / p [ @class='from']/a[@target='_blank']/text()").extract()[0]
16. item['tool']=card.xpath(".//p[@class='from']/a[@rel='nofollow']/text()").extract()[0]
17. i t e m [ ' c o n t e n t ' ] = c a r d . x p a t h ( " . / / p [ @class='txt']").extract()[1]
18. like_num=card.xpath(".//div[@class='cardact']//a[@action-type='feed_list_like']/em/text()").extract()[0]
19. item['like_num']=int(re.findall(r"\d+\.?\d*",like_num)[0])
20. repost_num=card.xpath(".//div[@class='cardact']//a[@action-type='feed_list_forward']/text()").extract()[0]
21. item['repost_num']=int(re.findall(r"\d+\.?\d*",repost_num)[0])
22. comment_num=card. xpath( ". //div[@class='card-act']//a[@action-type='feed_list_comment']/text()").extract()[0]
提取到的數(shù)據(jù)格式如圖5所示。
字段描述如圖6所示。
4.2.2移動端(觸屏版)頁面分析
觸屏版頁面抓包如圖7所示,頁面的數(shù)據(jù)是通過接口生成的,因此獲取數(shù)據(jù)更方便,其返回的是json格式的數(shù)據(jù),但是它只能返回1,000條數(shù)據(jù)。由于提取數(shù)據(jù)方便,因此可以協(xié)助研究人員從桌面端獲取數(shù)據(jù)。桌面端提取數(shù)據(jù)困難,但是在獲得微博ID和用戶ID的情況下,研究人員可切換為觸屏版通過接口提取數(shù)據(jù)。通過分析接口可以得到用戶詳細(xì)信息的數(shù)據(jù)接口為“http://m.weibo/cn/profile/info?uid=用戶ID”,微博詳情頁的數(shù)據(jù)接口為https://m.weibo.cn/comments/hotflow?id=微博ID&微博ID+&max_id=max_id&max_id_type=0,只需解析json數(shù)據(jù)便可提取數(shù)據(jù)。
提取的數(shù)據(jù)格式存儲后如圖8所示。
4.2.3移動端(weibo.cn)頁面分析
移動端頁面較為簡單,但其用戶的個人描述比觸屏版更全面,因此可通過上面提取到的用戶ID在移動端提取個人信息,其URL生成規(guī)則為https://weibo.cn/用戶ID/info。分析HTML頁面,如圖9所示,的標(biāo)簽里的內(nèi)容即為微博個人信息內(nèi)容。通過Xpath表達(dá)式"http://div[@class="c"]"提取所有包含個人信息的div塊,再通過正則切割字符串[9]提取其詳細(xì)內(nèi)容,并保存到數(shù)據(jù)原始數(shù)據(jù)庫中。
提取到的數(shù)據(jù)格式如圖10所示。
4.3 網(wǎng)絡(luò)爬蟲模塊
網(wǎng)絡(luò)爬蟲模塊主要包括以下子模塊(各子模塊調(diào)度流程如圖11所示)。
消息隊列模塊:主要用來存放初始的URL鏈接,以及后續(xù)提取到的URL鏈接,供爬蟲使用。
調(diào)度器模塊:負(fù)責(zé)分發(fā)Request請求,并且對提取到的URL進(jìn)行去重。
下載器模塊:接收調(diào)度器下發(fā)的請求,從微博下載數(shù)據(jù),即獲取微博的HTML頁面。
爬蟲模塊:接收下載器下載到的HTML頁面,通過Xpath表達(dá)式和正則表達(dá)式提取網(wǎng)頁中的數(shù)據(jù)。
中間件模塊:在調(diào)度器把Request請求分發(fā)給下載器時添加一些信息,如UA(User Agent,用戶代理),Cookie(儲存在用戶本地終端上的數(shù)據(jù)),meta等信息。
4.3.1消息隊列模塊
使用Redis(Remote Dictionary Server,遠(yuǎn)程字典服務(wù))存儲需要爬取的URL,可以多個爬蟲實例共享同一個消息隊列,從而實現(xiàn)分布式爬蟲,多個爬蟲可以依次從隊列中提取URL并記錄URL是否已請求過,使調(diào)度器模塊在調(diào)度時候能過濾掉重復(fù)的Requests請求,即實現(xiàn)不會多個爬蟲爬取同一個鏈接。
4.3.2調(diào)度器模塊
接收從Scrapy引擎發(fā)來的請求,壓入隊列,當(dāng)引擎再次請求的時候返回給引擎,決定下次爬取的URL鏈接,Scrapy原生的隊列并不支持多個爬蟲實例共享一個隊列,當(dāng)使用Scrapy-redis爬蟲后,運(yùn)行方式如圖12所示。
4.3.3中間件模塊
位于Scrapy引擎和其他模塊之間的模塊,可分為爬蟲中間件、調(diào)度中間件、下載器中間件。負(fù)責(zé)引擎到各個模塊之間的請求和響應(yīng)。這里主要實現(xiàn)Cookie中間件、IP(InternetProtocol,網(wǎng)際協(xié)議)代理中間件、UA中間件、重定向中間件(Redirect Middleware)等。
Cookie中間件:從準(zhǔn)備好的賬號池中隨機(jī)選取一個賬號,并把其傳入Request的meta域[包含了所有本次HTTP請求的Header信息,比如用戶IP地址和用戶Agent(代理)]中。
IP代理中間件:從準(zhǔn)備好的IP池中,隨機(jī)選取一個IP,并把其傳入Request的meta域中。
UA中間件:從準(zhǔn)備好的UA池中,隨機(jī)選取一個UA,并把其傳入Request的meta域中。
重定向中間件:當(dāng)Request請求響應(yīng)錯誤代碼(418,302,403)時,重新發(fā)送Request請求。
4.3.4下載器模塊
下載網(wǎng)頁的內(nèi)容(響應(yīng)的HTML頁面),并將網(wǎng)頁內(nèi)容返回給Spider(爬蟲)實例,其建立在名叫Twisted的高效異步模型上,這里表現(xiàn)為當(dāng)其發(fā)出一個Request請求后,不必等待其返回的結(jié)果,而是繼續(xù)發(fā)起其他請求,當(dāng)請求數(shù)據(jù)被返回時,通過調(diào)用回調(diào)函數(shù)處理響應(yīng)的數(shù)據(jù),整個過程中不會出現(xiàn)等待返回結(jié)果的情況。
4.3.5爬蟲模塊
從下載器返回的內(nèi)容(請求得到的HTML頁面)中提取微博評論、微博詳細(xì)信息、用戶個人信息和下一次請求的URL鏈接等數(shù)據(jù),即Item(Items類中包含的字段),必須在Spider目錄下編寫,繼承于RedisSpider類,當(dāng)從下載器中獲得返回的內(nèi)容后,通過Xpath表達(dá)式和正則表達(dá)式提取數(shù)據(jù)。
5結(jié)論(Conclusion)
通過本數(shù)據(jù)采集系統(tǒng)在網(wǎng)絡(luò)中的實際采集效果來看,微博的一個頁面最多有20 條微博信息,爬蟲每個頁面大概能爬取19 條數(shù)據(jù),一分鐘可采集612條數(shù)據(jù),單機(jī)日采集量約為88萬條。實際應(yīng)用中,用戶還可根據(jù)需求自定義爬取數(shù)據(jù)的速度,也可以通過增加分布式爬蟲數(shù)量提升爬取數(shù)據(jù)量與速度。通過爬取的數(shù)據(jù)生成的結(jié)論化數(shù)據(jù)來看,也與預(yù)期結(jié)果一致。當(dāng)采集的數(shù)據(jù)量過大時,在提升爬取數(shù)據(jù)量與爬取速度時,對于服務(wù)器的性能也有較高的要求,后期將在降數(shù)據(jù)規(guī)模算法方面進(jìn)行進(jìn)一步的優(yōu)化。
作者簡介:
霍英(1975-),女,博士,教授.研究領(lǐng)域:大數(shù)據(jù)與物聯(lián)網(wǎng),社會網(wǎng)絡(luò).
李小帆(1996-),男,本科,工程師.研究領(lǐng)域:輿情處理.
丘志敏(1973-),男,碩士,副教授.研究領(lǐng)域:社會網(wǎng)絡(luò).
李彥廷(1975-),男,博士,副教授.研究領(lǐng)域:輿情處理.