前言
? 很多同學(xué)會(huì)問(wèn):“為什么我的畢業(yè)設(shè)計(jì)總是過(guò)不了皮获?為什么我的畢設(shè)分?jǐn)?shù)很低?”這種情況要么就是你的畢設(shè)做得過(guò)于粗糙,要么就是功能過(guò)于簡(jiǎn)單初家,給導(dǎo)師的感覺(jué)就是很容易就能實(shí)現(xiàn),你小子壓根沒(méi)花時(shí)間去做乌助。你們說(shuō)是不是這個(gè)理兒溜在?
? 本期案例分享,學(xué)長(zhǎng)給大家上點(diǎn)干貨他托,手把手帶你開(kāi)發(fā)一個(gè)分布式爬蟲(chóng)系統(tǒng)掖肋。通過(guò)這個(gè)項(xiàng)目,你將學(xué)習(xí)到下面幾點(diǎn):
- 架構(gòu)設(shè)計(jì)赏参。如果設(shè)計(jì)一個(gè)通用的爬蟲(chóng)系統(tǒng)志笼?一個(gè)系統(tǒng)支持爬取所有的網(wǎng)站。
- 分布式開(kāi)發(fā)經(jīng)驗(yàn)把篓。分布式系統(tǒng)開(kāi)發(fā)考慮的點(diǎn)會(huì)更多纫溃,如何保證代碼在多節(jié)點(diǎn)部署時(shí)還能正確的運(yùn)行?
- 多線程開(kāi)發(fā)經(jīng)驗(yàn)韧掩。大量使用了concurrent包中的多線程類紊浩,多線程、線程池疗锐、鎖坊谁。結(jié)合真實(shí)的業(yè)務(wù)場(chǎng)景教你怎么玩轉(zhuǎn)多線程,跟你平時(shí)寫(xiě)的多線程demo是完全不同的滑臊。
鄭重聲明:本項(xiàng)目的出發(fā)點(diǎn)是學(xué)習(xí)和技術(shù)分享口芍,項(xiàng)目中出現(xiàn)的爬蟲(chóng)案例也都是互聯(lián)網(wǎng)上可以公開(kāi)訪問(wèn)的網(wǎng)站,爬取時(shí)嚴(yán)格控制了爬取頻率以及爬取速度(單線程去爬取雇卷,每爬取一個(gè)頁(yè)面休眠1秒阶界,最多爬取100個(gè)頁(yè)面)虹钮,絕不會(huì)影響目標(biāo)網(wǎng)站的正常運(yùn)行。
? (想要源碼膘融、文檔芙粱、視頻教程的同學(xué)請(qǐng)掃碼加我微信。這里打個(gè)廣告氧映,學(xué)長(zhǎng)多年bat工作經(jīng)驗(yàn)春畔,常年負(fù)責(zé)校招和社招面試,有興趣的同學(xué)可以私信我岛都,我可以提供簡(jiǎn)歷輔導(dǎo)和內(nèi)推~~~)
項(xiàng)目架構(gòu)
爬蟲(chóng)組件
上面是爬蟲(chóng)系統(tǒng)的經(jīng)典架構(gòu)圖律姨,簡(jiǎn)單說(shuō)下每個(gè)組件的職責(zé):
- Spiders:每個(gè)spider負(fù)責(zé)處理一個(gè)特殊的網(wǎng)站,負(fù)責(zé)抽取目標(biāo)網(wǎng)站的數(shù)據(jù)
- Scheduler:調(diào)度器從引擎接受request并將他們?nèi)腙?duì)臼疫,以便之后引擎請(qǐng)求他們時(shí)提供給引擎
- Downloader:根據(jù)request對(duì)象去執(zhí)行網(wǎng)絡(luò)下載
- Pipeline:負(fù)責(zé)將spider抽取出來(lái)的item數(shù)據(jù)進(jìn)行存儲(chǔ)择份,這里我們存儲(chǔ)在MySQL
最后我們合起來(lái)說(shuō)明下爬蟲(chóng)流程:
- 首先創(chuàng)建一個(gè)spider爬蟲(chóng)任務(wù),這時(shí)候會(huì)有一個(gè)入口URL烫堤,spider從這個(gè)入口開(kāi)始爬取
- 調(diào)用Downloader組件去執(zhí)行http請(qǐng)求下載整個(gè)頁(yè)面
- spider解析頁(yè)面中的內(nèi)容荣赶,將需要的內(nèi)容放入item里面,同時(shí)將頁(yè)面中的子URL放入Scheduler組件
- Pipeline負(fù)責(zé)將item中的數(shù)據(jù)就行持久化存儲(chǔ)
- URL放入Scheduler組件鸽斟,Scheduler組件會(huì)對(duì)URL進(jìn)行去重拔创,避免重復(fù)爬取
- spider爬完當(dāng)前頁(yè)面后就繼續(xù)從Scheduler拿URL,如果有URL則繼續(xù)爬取富蓄,沒(méi)有則說(shuō)明所有頁(yè)面都爬完了剩燥,spider任務(wù)結(jié)束
分布式爬蟲(chóng)
? 什么是分布式爬蟲(chóng)?用大白話來(lái)說(shuō)就是:我部署了多個(gè)爬蟲(chóng)模塊立倍,這幾個(gè)模塊可以一起來(lái)爬蟲(chóng)灭红。從上面架構(gòu)圖的分析,只需要將Scheduler模塊基于redis實(shí)現(xiàn)口注,那么所有的模塊的spider只需要從redis獲取URL变擒,然后爬到新的子URL時(shí)也放入redis中,此時(shí)我們的架構(gòu)已經(jīng)是支持分布式爬蟲(chóng)了疆导。(代碼細(xì)節(jié)較多,文章篇幅有限葛躏,不展開(kāi)細(xì)說(shuō)了)
定制化爬蟲(chóng)
? 對(duì)于一些頁(yè)面靜態(tài)化的網(wǎng)站澈段,做了SEO可以直接被搜索引擎爬取的網(wǎng)站、沒(méi)有做反爬的網(wǎng)站舰攒,這些網(wǎng)站我們是可以定制一個(gè)通用的爬蟲(chóng)策略來(lái)爬取败富,直接http請(qǐng)求,然后解析內(nèi)容和圖片等資源摩窃。而對(duì)于一些做了反爬策略的兽叮,例如分頁(yè)的數(shù)據(jù)芬骄、動(dòng)態(tài)渲染的網(wǎng)頁(yè)、請(qǐng)求頭攔截鹦聪、ip高頻攔截等等账阻。對(duì)于這類網(wǎng)站的爬蟲(chóng)需要做一些定制化的邏輯,所以在架構(gòu)設(shè)計(jì)上泽本,學(xué)長(zhǎng)提供了一個(gè)爬蟲(chóng)訂制模板的入口淘太,通過(guò)在代碼中開(kāi)發(fā)針對(duì)具體網(wǎng)站的定制化爬蟲(chóng)策略,這樣就可以避開(kāi)大多數(shù)的反爬規(guī)則规丽,從而實(shí)現(xiàn)一個(gè)爬蟲(chóng)系統(tǒng)可以支持絕大多數(shù)的網(wǎng)站爬取蒲牧。
領(lǐng)域模型
DO(DataObject):與數(shù)據(jù)庫(kù)表結(jié)構(gòu)一一對(duì)應(yīng),通過(guò)DAO層向上傳輸數(shù)據(jù)源對(duì)象
BO(BusinessObject):業(yè)務(wù)對(duì)象赌莺。由Service層輸出的封裝業(yè)務(wù)邏輯的對(duì)象
-
VO(View Object):顯示層對(duì)象冰抢,通常是Web向模板渲染引擎層傳輸?shù)膶?duì)象
BO和VO領(lǐng)域模型又分為BoRequest(輸入模型)、BoResponse(輸出模型)艘狭、VoRequest(輸入模型)挎扰、VoResponse(輸出模型)
技術(shù)棧
前端:vue + element
后端:jdk1.8 + springboot + redis + mysql + jsoup + httpClient
權(quán)限:security+spring-session
接口設(shè)計(jì)
? 整個(gè)項(xiàng)目接口采用的目前互聯(lián)網(wǎng)比較流行的restful風(fēng)格設(shè)計(jì),每個(gè)接口缓升、每個(gè)參數(shù)都有詳細(xì)的文檔說(shuō)明鼓鲁。因?yàn)槠髽I(yè)中開(kāi)發(fā)必然是團(tuán)隊(duì)協(xié)作,必然前后端分離的開(kāi)發(fā)模式港谊,你得先把接口定義出來(lái)骇吭,然后前端可以和后端同步開(kāi)發(fā)。還有一種就是對(duì)外提供接口歧寺,比如你們隔壁團(tuán)隊(duì)也想調(diào)用你這個(gè)服務(wù)的接口燥狰,但是你兩排期是同一周,這時(shí)候你得先把接口定義出來(lái)給人家斜筐,然后大家同步開(kāi)發(fā)龙致,開(kāi)發(fā)完了之后再進(jìn)行聯(lián)調(diào)。
運(yùn)行效果
系統(tǒng)登錄
dashboard
實(shí)時(shí)統(tǒng)計(jì)系統(tǒng)數(shù)據(jù)
任務(wù)管理
頁(yè)面菜單顷链、“查詢”目代、“創(chuàng)建”、“編輯”嗤练、“刪除”按鈕都支持單獨(dú)的權(quán)限分配榛了,這里列舉了爬蟲(chóng)案例,“爬取百度新聞”煞抬、“爬取必應(yīng)壁紙”霜大、“爬取當(dāng)當(dāng)網(wǎng)書(shū)籍信息”、“爬取新浪新聞”
創(chuàng)建爬蟲(chóng)任務(wù)
爬取必應(yīng)壁紙
? 很多人用必應(yīng)搜索是因?yàn)橄矚g必應(yīng)的高清壁紙(學(xué)長(zhǎng)就是這樣的)革答,這里演示必應(yīng)壁紙的爬蟲(chóng)战坤。因?yàn)楸貞?yīng)壁紙涉及分頁(yè)曙强,這里剛好用到我們的訂制模板功能,通過(guò)寫(xiě)一個(gè)BingTemplate模板途茫,我們可以輕松地搞定分頁(yè)數(shù)據(jù)爬蟲(chóng)碟嘴。
? 文明爬蟲(chóng),我們只爬了100頁(yè)數(shù)據(jù)慈省,每頁(yè)的圖片都在資源詳情里面臀防,非常漂亮,可以點(diǎn)擊放大圖片并下載
[圖片上傳失敗...(image-ab2aa-1612190377490)].jpg)
爬取當(dāng)當(dāng)網(wǎng)
? 之前學(xué)長(zhǎng)在專欄分享過(guò)《圖書(shū)管理系統(tǒng)》边败,當(dāng)時(shí)為了讓內(nèi)容更真實(shí)袱衷,從當(dāng)當(dāng)網(wǎng)爬取了一些書(shū)籍信息,比如書(shū)名笑窜、作者致燥、出版社、價(jià)格排截、簡(jiǎn)介等信息嫌蚤。(感興趣的可以去專欄回顧下圖書(shū)管理系統(tǒng)的設(shè)計(jì)和實(shí)現(xiàn))
? 訂制一個(gè)當(dāng)當(dāng)網(wǎng)的爬蟲(chóng)模板DangDangTemplate,只須一個(gè)URL断傲,開(kāi)始我們的訂制爬蟲(chóng)之旅脱吱。
爬取百度和新浪新聞
? 百度新聞和新浪新聞都比較好爬,不需要模板认罩,直接新建任務(wù)箱蝠,只需要填入一個(gè)URL,立即開(kāi)始爬蟲(chóng)垦垂。
資源管理
所有爬取到的數(shù)據(jù)都可以在資源管理界面查詢到宦搬,點(diǎn)擊“資源詳情”可以看到具體的文本、圖片內(nèi)容劫拗,圖片支持放大间校、下載、以及幻燈片播放
模板管理
? 前面已經(jīng)說(shuō)過(guò)页慷,對(duì)于有反爬策略的網(wǎng)站和定制化的爬蟲(chóng)都可以通過(guò)開(kāi)發(fā)一個(gè)爬蟲(chóng)模板來(lái)實(shí)現(xiàn)憔足,這樣的設(shè)計(jì)對(duì)系統(tǒng)擴(kuò)展性是非常好的,等于說(shuō)一個(gè)爬蟲(chóng)系統(tǒng)可以爬取所有的內(nèi)容酒繁。
日志管理
? 日志管理默認(rèn)是開(kāi)給管理員的滓彰,在系統(tǒng)中的所有操作都會(huì)被記錄,在系統(tǒng)出現(xiàn)異常時(shí)也便于管理員進(jìn)行問(wèn)題排查欲逃。
用戶管理
? 默認(rèn)也是只有管理員擁有用戶管理菜單的權(quán)限找蜜,可以新建/編輯用戶饼暑、分配用戶角色稳析、禁用/啟用等操作
編輯用戶信息
? 擁有賬號(hào)編輯權(quán)限的用戶可以進(jìn)行編輯操作
角色管理
? 默認(rèn)也是只有管理員擁有角色管理菜單的權(quán)限洗做,這里的權(quán)限是細(xì)粒度到按鈕權(quán)限的,每個(gè)按鈕都可以進(jìn)行權(quán)限管理彰居,假如給用戶只分配了任務(wù)的“查詢”權(quán)限诚纸,但是這個(gè)用戶是個(gè)程序員,他想通過(guò)接口請(qǐng)求直接訪問(wèn)任務(wù)修改接口陈惰,這時(shí)候后端是會(huì)權(quán)限校驗(yàn)的畦徘,返回“未授權(quán)”的錯(cuò)誤碼,然后前端根據(jù)“未授權(quán)”錯(cuò)誤碼會(huì)重定向到一個(gè)403頁(yè)面(這也是為什么說(shuō)只有前端校驗(yàn)是不安全的抬闯,后端也必須得校驗(yàn)井辆,這在實(shí)際企業(yè)里開(kāi)發(fā)也是這樣的,還沒(méi)有實(shí)際開(kāi)發(fā)經(jīng)驗(yàn)的學(xué)弟學(xué)妹拿個(gè)小本本記一記溶握,哈哈哈)
權(quán)限設(shè)計(jì)
? 權(quán)限基于security和spring-session實(shí)現(xiàn)杯缺。權(quán)限可以分為認(rèn)證和授權(quán),認(rèn)證其實(shí)就是登錄睡榆,用戶登錄時(shí)會(huì)進(jìn)行賬號(hào)密碼的校驗(yàn)萍肆,校驗(yàn)成功后會(huì),會(huì)把session存入redis中胀屿。授權(quán)指的是用戶是否擁有訪問(wèn)后端資源的權(quán)限塘揣,每個(gè)新用戶在創(chuàng)建后都會(huì)分配角色,角色其實(shí)就是一個(gè)權(quán)限集合宿崭,這里的權(quán)限可以理解為訪問(wèn)后端一個(gè)個(gè)接口(資源)的權(quán)限亲铡。
? 這里權(quán)限設(shè)計(jì)的非常靈活,細(xì)粒度到按鈕級(jí)別劳曹,比如課程菜單的新增奴愉、刪除、修改铁孵、查詢動(dòng)作锭硼,學(xué)生可能只有課程的查詢權(quán)限,無(wú)法新增和修改課程蜕劝,即使通過(guò)接口直接訪問(wèn)后端的修改或者新增接口檀头,后端也會(huì)返回授權(quán)失敗錯(cuò)誤,因?yàn)楹蠖嗣總€(gè)需要權(quán)限的接口都打了權(quán)限標(biāo)識(shí)岖沛,只有擁有資源權(quán)限用戶才能訪問(wèn)暑始。
日志方案
? 日志采用lombok注解+slf4j+log4j2的實(shí)現(xiàn)方案,基于profile實(shí)現(xiàn)了多環(huán)境的日志配置婴削,因?yàn)椴煌h(huán)境的日志打印策略是不一樣廊镜,比如開(kāi)發(fā)環(huán)境我可能需要打印到console控制臺(tái),需要debug級(jí)別的日志以便于本地開(kāi)發(fā)調(diào)試唉俗,測(cè)試環(huán)境可能就需要打印到日志文件里嗤朴,線上環(huán)境可能需要打印到文件的同時(shí)將日志發(fā)送到kafka然后收集到es中配椭,這樣當(dāng)線上部署了多臺(tái)機(jī)器后我們查日志不用一臺(tái)一臺(tái)機(jī)器去查日志了,因?yàn)槎际占絜s了雹姊,我們只需要登錄kibana去搜索股缸,這樣就非常方便。這里說(shuō)到的kafka+es+kibana這樣一套日志解決方案也是目前互聯(lián)網(wǎng)公司比較常用的一套解決方案吱雏。如果你動(dòng)手能力夠強(qiáng)敦姻,你可以本地搭一套kafka、es歧杏、kibana镰惦,然后只需要在配置文件中加入幾行配置就實(shí)現(xiàn)了這么一套企業(yè)級(jí)的日志解決方案(默認(rèn)是輸出到日志文件)。
下面是部分關(guān)鍵配置犬绒,如果要配置kafka陨献,只需要在<Appenders>標(biāo)簽中配置<Kafka>配置即可
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN" xmlns:xi="http://www.w3.org/2001/XInclude">
<Properties>
<Property name="LOG_FILE">system.log</Property>
<Property name="LOG_PATH">./logs</Property>
<Property name="PID">????</Property>
<Property name="LOG_EXCEPTION_CONVERSION_WORD">%xwEx</Property>
<Property name="LOG_LEVEL_PATTERN">%5p</Property>
<Property name="LOG_DATE_FORMAT_PATTERN">yyyy-MM-dd HH:mm:ss.SSS</Property>
<Property name="CONSOLE_LOG_PATTERN">%clr{%d{${LOG_DATE_FORMAT_PATTERN}}}{faint} %clr{${LOG_LEVEL_PATTERN}} %clr{${sys:PID}}{magenta} %clr{---}{faint} %clr{[%15.15t]}{faint} %clr{%-40.40c{1.}}{cyan} %clr{:}{faint} %m%n${sys:LOG_EXCEPTION_CONVERSION_WORD}
</Property>
<Property name="FILE_LOG_PATTERN">%d{${LOG_DATE_FORMAT_PATTERN}} ${LOG_LEVEL_PATTERN} ${sys:PID} --- [%t] %-40.40c{1.}:%L : %m%n${sys:LOG_EXCEPTION_CONVERSION_WORD}
</Property>
</Properties>
<Appenders>
<xi:include href="log4j2/file-appender.xml"/>
</Appenders>
<Loggers>
<logger name="com.senior.book" level="info"/>
<Root level="info">
<AppenderRef ref="FileAppender"/>
</Root>
</Loggers>
</Configuration>
服務(wù)監(jiān)控
? 服務(wù)監(jiān)控基于 Actuator + Prometheus + Grafana 實(shí)現(xiàn),代碼侵入很小懂更,只需要在pom中加入依賴眨业。數(shù)據(jù)大盤Dashboard可以自己設(shè)置,也可以去Dashboard市場(chǎng)下載你想要的模板沮协,總之龄捡,這塊完全是看動(dòng)手能力,大家自己玩吧~~~
<!--服務(wù)監(jiān)控-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>