本篇文章給大家?guī)?lái)了關(guān)于java的相關(guān)知識(shí),其中主要介紹了關(guān)于WebMagic的相關(guān)內(nèi)容,WebMagic是一個(gè)簡(jiǎn)單靈活的Java爬蟲框架,分為核心和擴(kuò)展兩部分,下面一起來(lái)看一下,希望對(duì)大家有幫助。
程序員必備接口測(cè)試調(diào)試工具:立即使用
Apipost = Postman + Swagger + Mock + Jmeter
Api設(shè)計(jì)、調(diào)試、文檔、自動(dòng)化測(cè)試工具
后端、前端、測(cè)試,同時(shí)在線協(xié)作,內(nèi)容實(shí)時(shí)同步
推薦學(xué)習(xí):《java視頻教程》
概述
WebMagic是一個(gè)簡(jiǎn)單靈活的Java爬蟲框架。基于WebMagic,可以快速開發(fā)出一個(gè)高效、易維護(hù)的爬蟲。
WebMagic分為核心和擴(kuò)展兩部分。核心部分(webmagic-core)是一個(gè)精簡(jiǎn)的、模塊化的爬蟲實(shí)現(xiàn),而擴(kuò)展部分則包括一些便利的、實(shí)用性的功能。
特性
簡(jiǎn)單的API,可快速上手
模塊化的結(jié)構(gòu),可輕松擴(kuò)展
提供多線程和分布式支持
架構(gòu)
WebMagic的結(jié)構(gòu)分為Downloader、PageProcessor、Scheduler、Pipeline四大組件,并由Spider將它們彼此組織起來(lái)。
四大組件對(duì)應(yīng)爬蟲生命周期中的下載、處理、管理和持久化等功能。WebMagic的設(shè)計(jì)參考了Scapy,實(shí)現(xiàn)方式更加Java化一些。
Spider則將這幾個(gè)組件組織起來(lái),讓它們可以互相交互,流程化的執(zhí)行,可以認(rèn)為Spider是一個(gè)大的容器,它也是WebMagic邏輯的核心。
四大組件
Downloader
Downloader負(fù)責(zé)從互聯(lián)網(wǎng)上下載頁(yè)面,以便后續(xù)處理。WebMagic默認(rèn)使用了Apache HttpClient作為下載工具。
PageProcessor
PageProcessor負(fù)責(zé)解析頁(yè)面,抽取有用信息,以及發(fā)現(xiàn)新的鏈接。WebMagic使用Jsoup作為HTML解析工具,并基于其開發(fā)了解析XPath的工具Xsoup。
在這四個(gè)組件中,PageProcessor對(duì)于每個(gè)站點(diǎn)每個(gè)頁(yè)面都不一樣,是需要使用者定制的部分。
Scheduler
Scheduler負(fù)責(zé)管理待抓取的URL,以及一些去重的工作。WebMagic默認(rèn)提供了JDK的內(nèi)存隊(duì)列來(lái)管理URL,并用集合來(lái)進(jìn)行去重。也支持使用Redis進(jìn)行分布式管理。
Pipeline
Pipeline負(fù)責(zé)抽取結(jié)果的處理,包括計(jì)算、持久化到文件、數(shù)據(jù)庫(kù)等。WebMagic默認(rèn)提供了“輸出到控制臺(tái)”和“保存到文件”兩種結(jié)果處理方案。
Pipeline定義了結(jié)果保存的方式,如果你要保存到指定數(shù)據(jù)庫(kù),則需要編寫對(duì)應(yīng)的Pipeline。對(duì)于一類需求一般只需編寫一個(gè)Pipeline。
數(shù)據(jù)流轉(zhuǎn)對(duì)象
Request
Request是對(duì)URL地址的一層封裝,一個(gè)Request對(duì)應(yīng)一個(gè)URL地址。它是PageProcessor與Downloader交互的載體,也是PageProcessor控制Downloader唯一方式。
除了URL本身外,它還包含一個(gè)Key-Value結(jié)構(gòu)的字段extra。你可以在extra中保存一些特殊的屬性,然后在其他地方讀取,以完成不同的功能。例如附加上一個(gè)頁(yè)面的一些信息等。
Page
Page代表了從Downloader下載到的一個(gè)頁(yè)面——可能是HTML,也可能是JSON或者其他文本格式的內(nèi)容。
Page是WebMagic抽取過(guò)程的核心對(duì)象,它提供一些方法可供抽取、結(jié)果保存等。
ResultItems
ResultItems相當(dāng)于一個(gè)Map,它保存PageProcessor處理的結(jié)果,供Pipeline使用。它的API與Map很類似,值得注意的是它有一個(gè)字段skip,若設(shè)置為true,則不應(yīng)被Pipeline處理。
控制爬蟲運(yùn)轉(zhuǎn)的引擎Spider
Spider是WebMagic內(nèi)部流程的核心。Downloader、PageProcessor、Scheduler、Pipeline都是Spider的一個(gè)屬性,這些屬性是可以自由設(shè)置的,通過(guò)設(shè)置這個(gè)屬性可以實(shí)現(xiàn)不同的功能。Spider也是WebMagic操作的入口,它封裝了爬蟲的創(chuàng)建、啟動(dòng)、停止、多線程等功能。
以下是一個(gè)設(shè)置各個(gè)組件,并且設(shè)置多線程和啟動(dòng)的例子。
public static void main(String[] args) { Spider.create(new GithubRepoPageProcessor()) //從https://github.com/code4craft開始抓 .addUrl("https://github.com/code4craft") //設(shè)置Scheduler,使用Redis來(lái)管理URL隊(duì)列 .setScheduler(new RedisScheduler("localhost")) //設(shè)置Pipeline,將結(jié)果以json方式保存到文件 .addPipeline(new JsonFilePipeline("D:\data\webmagic")) //開啟5個(gè)線程同時(shí)執(zhí)行 .thread(5) //啟動(dòng)爬蟲 .run(); }
WebMagic的基本使用
添加WebMagic的核心與擴(kuò)展依賴
<dependency> <groupId>us.codecraft</groupId> <artifactId>webmagic-core</artifactId> <version>0.7.5</version> </dependency> <dependency> <groupId>us.codecraft</groupId> <artifactId>webmagic-extension</artifactId> <version>0.7.5</version> </dependency>
爬蟲實(shí)現(xiàn)
public class MyJobProcessor implements PageProcessor { public void process(Page page) { List<String> all = page.getHtml().css("span.s_btn_wr").css("input").all(); page.putField("title", all.get(0)); } private Site site = Site.me() //設(shè)置編碼 .setCharset("utf8") //設(shè)置超時(shí)時(shí)間,單位是ms毫秒 .setTimeOut(10000) //設(shè)置重試的間隔時(shí)間 .setRetrySleepTime(3000) //設(shè)置重試次數(shù) .setSleepTime(3); public Site getSite() { return site; } public static void main(String[] args) { Spider.create(new MyJobProcessor()) //初始訪問(wèn)url地址 .addUrl("http://www.baidu.com") .run(); } }
get page: http://www.baidu.com title:<input type="submit" id="su" value="百度一下" class="bg s_btn">
爬蟲的編寫過(guò)程
實(shí)現(xiàn)PageProcessor
PageProcessor的定制分為三個(gè)部分,分別是爬蟲的配置、頁(yè)面元素的抽取和鏈接的發(fā)現(xiàn)
爬蟲配置
爬蟲的配置,包括編碼、抓取間隔、超時(shí)時(shí)間、重試次數(shù)等,也包括一些模擬的參數(shù),例如User Agent、cookie,以及代理的設(shè)置。
private Site site = Site.me() //設(shè)置編碼 .setCharset("utf8") //設(shè)置超時(shí)時(shí)間,單位是ms毫秒 .setTimeOut(10000) //設(shè)置重試的間隔時(shí)間 .setRetrySleepTime(3000) //設(shè)置重試次數(shù) .setSleepTime(3);
抽取頁(yè)面元素
頁(yè)面元素的抽取是爬蟲的核心部分:對(duì)于下載到的Html頁(yè)面,如何從中抽取到想要的信息?
WebMagic主要使用三種抽取技術(shù):XPath、正則表達(dá)式和CSS選擇器。對(duì)于JSON格式的內(nèi)容,可使用JsonPath進(jìn)行解析
XPath
獲取屬性class=myClass的div標(biāo)簽,里面的h1標(biāo)簽的內(nèi)容
page.getHtml().xpath("//div[@class=myClass]/h1/text()")
CSS選擇器
CSS選擇器是與XPath類似的語(yǔ)言。Jsoup的選擇器比XPath寫起來(lái)要簡(jiǎn)單一些,但是如果寫復(fù)雜一點(diǎn)的抽取規(guī)則,就相對(duì)要麻煩一點(diǎn)。
獲取屬性class為myClass的div標(biāo)簽下的直接子元素h1標(biāo)簽
page.getHtml().css("div.mt>h1").toString()
可使用:nth-child(n)選擇第幾個(gè)元素,但是注意:需要使用直接子元素才可以選擇第幾個(gè)元素
如: 選擇第一個(gè)元素
page.getHtml().css("div#myId > ul > li:nth-child(1) a").toString()
正則表達(dá)式
正則表達(dá)式則是一種通用的文本抽取語(yǔ)言。在這里一般用于獲取url地址。
匹配所有https://github.com/code4craft/webmagic這樣的鏈接。
page.addTargetRequests(page.getHtml().links().regex("(https://github\.com/\w+/\w+)").all());
JsonPath
JsonPath是于XPath很類似的一個(gè)語(yǔ)言,它用于從Json中快速定位一條內(nèi)容。
鏈接的發(fā)現(xiàn)
一個(gè)站點(diǎn)的頁(yè)面是很多的,一開始不可能全部列舉出來(lái),于是如何發(fā)現(xiàn)后續(xù)的鏈接,是一個(gè)爬蟲不可缺少的一部分。
page.addTargetRequests(page.getHtml().links().regex("(https://github\.com/\w+/\w+)").all());
page.getHtml().links().regex("(https://github\.com/\w+/\w+)").all()用于獲取所有滿足https:/ /github.com/w+/w+這個(gè)正則表達(dá)式的鏈接
page.addTargetRequests()則將這些鏈接加入到待抓取的隊(duì)列中去。
Selectable抽取元素
Selectable相關(guān)的抽取元素鏈?zhǔn)紸PI是WebMagic的一個(gè)核心功能。使用Selectable接口,就可以直接完成頁(yè)面元素的鏈?zhǔn)匠槿。矡o(wú)需去關(guān)心抽取的細(xì)節(jié)。
上述page.getHtml()返回的是一個(gè)Html對(duì)象,它實(shí)現(xiàn)了Selectable接口。這個(gè)接口包含一些重要的方法,將它分為兩類:抽取部分和獲取結(jié)果部分。
抽取部分API
抽取部分API返回的都是一個(gè)Selectable接口,是支持鏈?zhǔn)秸{(diào)用的。
獲取結(jié)果的API
當(dāng)鏈?zhǔn)秸{(diào)用結(jié)束時(shí),一般都想要拿到一個(gè)字符串類型的結(jié)果。這時(shí)候就需要用到獲取結(jié)果的API了。
一條抽取規(guī)則,無(wú)論是XPath、CSS選擇器或者正則表達(dá)式,總有可能抽取到多條元素。WebMagic對(duì)這些進(jìn)行了統(tǒng)一,可以通過(guò)不同的API獲取到一個(gè)或者多個(gè)元素。
注意:當(dāng)有多條數(shù)據(jù)的時(shí)候,使用get()和toString()都是獲取第一個(gè)url地址。
使用Pipeline保存結(jié)果
如何將抓取的結(jié)果保存下來(lái)?WebMagic用于保存結(jié)果的組件叫做Pipeline。
例如通過(guò)“控制臺(tái)輸出結(jié)果”這件事也是通過(guò)一個(gè)內(nèi)置的Pipeline完成的,它叫做ConsolePipeline。
想要把結(jié)果用Json的格式保存下來(lái),只需要將Pipeline的實(shí)現(xiàn)換成"JsonFilePipeline"就可以了。
想要把結(jié)果用保存到文件中,只將Pipeline的實(shí)現(xiàn)換成"FilePipeline"就可以了。
public static void main(String[] args) { Spider.create(new GithubRepoPageProcessor()) // 初始訪問(wèn)url地址 .addUrl("https://github.com/code4craft") .addPipeline(new JsonFilePipeline("D:\webmagic\")) //.addPipeline(new FilePipeline("D:\webmagic\")) //開啟5個(gè)線程抓取 .thread(5) //啟動(dòng)爬蟲 .run(); }
爬蟲的配置、啟動(dòng)和終止
Spider啟動(dòng)入口
Spider是爬蟲啟動(dòng)的入口。在啟動(dòng)爬蟲之前,需要使用一個(gè)PageProcessor創(chuàng)建一個(gè)Spider對(duì)象,然后使用run()進(jìn)行啟動(dòng)。同時(shí)Spider的其他組件(Downloader、Scheduler、Pipeline)都可以通過(guò)set方法來(lái)進(jìn)行設(shè)置。
Site爬蟲配置
對(duì)站點(diǎn)本身的一些配置信息,例如編碼、HTTP頭、超時(shí)時(shí)間、重試策略等、代理等,都可以通過(guò)設(shè)置Site對(duì)象來(lái)進(jìn)行配置。
rivate Site site = Site.me() .setCharset("UTF-8")//編碼 .setSleepTime(1)//抓取間隔時(shí)間 .setTimeOut(1000*10)//超時(shí)時(shí)間 .setRetrySleepTime(3000)//重試時(shí)間 .setRetryTimes(3);//重試次數(shù)
配置代理
代理服務(wù)器
有些網(wǎng)站不允許爬蟲進(jìn)行數(shù)據(jù)爬取,因?yàn)闀?huì)加大服務(wù)器的壓力。其中一種最有效的方式是通過(guò)ip+時(shí)間進(jìn)行鑒別,因?yàn)檎H瞬豢赡芏虝r(shí)間開啟太多的頁(yè)面,發(fā)起太多的請(qǐng)求。
使用WebMagic可以設(shè)置爬取數(shù)據(jù)的時(shí)間,但是會(huì)大大降低爬取數(shù)據(jù)的效率。如果ip被禁了,就有必要使用代理服務(wù)器來(lái)爬取數(shù)據(jù)。
代理(Proxy),也稱網(wǎng)絡(luò)代理,是一種特殊的網(wǎng)絡(luò)服務(wù),允許一個(gè)網(wǎng)絡(luò)終端(一般為客戶端)通過(guò)這個(gè)服務(wù)與另一個(gè)網(wǎng)絡(luò)終端(一般為服務(wù)器)進(jìn)行非直接的連接。
提供代理服務(wù)的電腦系統(tǒng)或其它類型的網(wǎng)絡(luò)終端稱為代理服務(wù)器(Proxy Server)。一個(gè)完整的代理請(qǐng)求過(guò)程為:客戶端首先與代理服務(wù)器創(chuàng)建連接,接著根據(jù)代理服務(wù)器所使用的代理協(xié)議,請(qǐng)求對(duì)目標(biāo)服務(wù)器創(chuàng)建連接、或者獲得目標(biāo)服務(wù)器的指定資源。
使用代理服務(wù)器
WebMagic使用的代理對(duì)象是APIProxyProvider。代理由HttpClientDownloader設(shè)置。
ProxyProvider有一個(gè)默認(rèn)實(shí)現(xiàn):SimpleProxyProvider。它是一個(gè)基于簡(jiǎn)單Round-Robin的、沒(méi)有失敗檢查的ProxyProvider。可以配置任意個(gè)候選代理,每次會(huì)按順序挑選一個(gè)代理使用。它適合用在自己搭建的比較穩(wěn)定的代理的場(chǎng)景。
如果需要根據(jù)實(shí)際使用情況對(duì)代理服務(wù)器進(jìn)行管理(例如校驗(yàn)是否可用,定期清理、添加代理服務(wù)器等),只需要自己實(shí)現(xiàn)APIProxyProvider
在Spider啟動(dòng)入口處配置代理
public void Process() { // 創(chuàng)建下載器Downloader HttpClientDownloader httpClientDownloader = new HttpClientDownloader(); // 給下載器設(shè)置代理服務(wù)器信息 Proxy proxy = new Proxy("183.166.148.28", 64305); httpClientDownloader.setProxyProvider(SimpleProxyProvider.from(proxy)); Spider.create(new ProxyTest()) // 淘寶獲取本機(jī)IP地址 .addUrl("https://www.taobao.com/help/getip.php") .setDownloader(httpClientDownloader) .run(); }
Scheduler組件
概述
Scheduler是WebMagic中進(jìn)行URL管理的組件。
Scheduler包括兩個(gè)作用:
對(duì)待抓取的URL隊(duì)列進(jìn)行管理。
對(duì)已抓取的URL進(jìn)行去重。
WebMagic內(nèi)置了幾個(gè)常用的Scheduler。如果只是在本地執(zhí)行規(guī)模比較小的爬蟲,那么基本無(wú)需定制Scheduler
對(duì)Scheduler的內(nèi)部實(shí)現(xiàn)進(jìn)行了重構(gòu),去重部分被單獨(dú)抽象成了一個(gè)接口:DuplicateRemover,從而可以為同一個(gè)Scheduler選擇不同的去重方式,以適應(yīng)不同的需要,目前提供了兩種去重方式。
所有默認(rèn)的Scheduler都使用HashSetDuplicateRemover來(lái)進(jìn)行去重,除了RedisScheduler。
RedisScheduler是使用Redis的set進(jìn)行去重,其他的Scheduler默認(rèn)都使用HashSetDuplicateRemover來(lái)進(jìn)行去重。
如果URL較多,使用HashSetDuplicateRemover會(huì)比較占用內(nèi)存,可嘗試BloomFilterDuplicateRemover
使用布隆過(guò)濾器
布隆過(guò)濾器 (Bloom Filter)是一種space efficient的概率型數(shù)據(jù)結(jié)構(gòu),用于判斷一個(gè)元素是否在集合中。在垃圾郵件過(guò)濾的黑白名單方法、爬蟲(Crawler)的網(wǎng)址判重模塊中等等經(jīng)常被用到。
哈希表也能用于判斷元素是否在集合中,但是布隆過(guò)濾器只需要哈希表的1/8或1/4的空間復(fù)雜度就能完成同樣的問(wèn)題。
布隆過(guò)濾器可以插入元素,但不可以刪除已有元素。其中的元素越多,誤報(bào)率越大,但是漏報(bào)是不可能的。
原理:
布隆過(guò)濾器需要的是一個(gè)位數(shù)組(和位圖類似)和K個(gè)映射函數(shù)(和Hash表類似),在初始狀態(tài)時(shí),對(duì)于長(zhǎng)度為m的位數(shù)組array,它的所有位被置0。
如果要使用BloomFilter,必須要加入以下依賴:
<!--WebMagic對(duì)布隆過(guò)濾器的支持--> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>31.1-jre</version> </dependency>
添加布隆過(guò)濾器
public static void main(String[] args) { Spider.create(new JobProcessor()) //初始訪問(wèn)url地址 .addUrl("https://github.com/code4craft") .addPipeline(new FilePipeline("D:/webmagic/")) .setScheduler(new QueueScheduler() .setDuplicateRemover(new BloomFilterDuplicateRemover(10000000))) //參數(shù)設(shè)置需要對(duì)多少條數(shù)據(jù)去重 .thread(1)//設(shè)置線程數(shù) .run(); }
public boolean isDuplicate(Request request, Task task) { boolean isDuplicate = this.bloomFilter.mightContain(this.getUrl(request)); if (!isDuplicate) { this.bloomFilter.put(this.getUrl(request)); this.counter.incrementAndGet(); } return isDuplicate; }
打開布隆過(guò)濾器BloomFilterDuplicateRemover,在isDuplicate方法處可斷點(diǎn)驗(yàn)證
對(duì)比
HashSet
使用java中的HashSet不能重復(fù)的特點(diǎn)去重。優(yōu)點(diǎn)是容易理解。使用方便。缺點(diǎn):占用內(nèi)存大,性能較低。
Redis去重
使用Redis的set進(jìn)行去重。優(yōu)點(diǎn)是速度快(Redis本身速度就很快),而且去重不會(huì)占用爬蟲服務(wù)器的資源,可以處理更大數(shù)據(jù)量的數(shù)據(jù)爬取。缺點(diǎn):需要準(zhǔn)備Redis服務(wù)器,增加開發(fā)和使用成本。
布隆過(guò)濾器(BloomFilter)
使用布隆過(guò)濾器也可以實(shí)現(xiàn)去重。優(yōu)點(diǎn)是占用的內(nèi)存要比使用HashSet要小的多,也適合大量數(shù)據(jù)的去重操作。缺點(diǎn):有誤判的可能。沒(méi)有重復(fù)可能會(huì)判定重復(fù),但是重復(fù)數(shù)據(jù)一定會(huì)判定重復(fù)。
布隆過(guò)濾器的實(shí)現(xiàn)
public class BloomFilter { /** * BitSet初始分配2^24個(gè)bit */ private static final int DEFAULT_SIZE = 1 << 24; /** * 不同哈希函數(shù)的種子,一般應(yīng)取質(zhì)數(shù) */ private static final int[] seeds = new int[]{5, 7, 11, 13, 31, 37}; private BitSet bits = new BitSet(DEFAULT_SIZE); /** * 哈希函數(shù)對(duì)象 */ private SimpleHash[] func = new SimpleHash[seeds.length]; public BloomFilter() { for (int i = 0; i < seeds.length; i++) { func[i] = new SimpleHash(DEFAULT_SIZE, seeds[i]); } } /** * 將url標(biāo)記到bits中 * * @param str */ public void add(String str) { for (SimpleHash f : func) { bits.set(f.hash(str), true); } } /** * 判斷是否已經(jīng)被bits標(biāo)記 * * @param str * @return */ public boolean contains(String str) { if (StringUtils.isBlank(str)) { return false; } boolean ret = true; for (SimpleHash f : func) { ret = ret && bits.get(f.hash(str)); } return ret; } /** * 哈希函數(shù)類 */ public static class SimpleHash { private int cap; private int seed; public SimpleHash(int cap, int seed) { this.cap = cap; this.seed = seed; } /** * hash函數(shù),采用簡(jiǎn)單的加權(quán)和hash * * @param value * @return */ public int hash(String value) { int result = 0; int len = value.length(); for (int i = 0; i < len; i++) { result = seed * result + value.charAt(i); } return (cap - 1) & result; } } }
Pipeline組件
概述
Pileline是抽取結(jié)束后,進(jìn)行處理的部分,它主要用于抽取結(jié)果的保存,也可以定制Pileline可以實(shí)現(xiàn)一些通用的功能。
Pipeline是將PageProcessor抽取的結(jié)果,繼續(xù)進(jìn)行處理,在Pipeline中完成的功能,基本上也可以直接在PageProcessor實(shí)現(xiàn)。
Pipeline的接口定義
public interface Pipeline { // ResultItems保存了抽取結(jié)果,它是一個(gè)Map結(jié)構(gòu) // 在page.putField(key,value)中保存的數(shù)據(jù),可以通過(guò)ResultItems.get(key)獲取 public void process(ResultItems resultItems, Task task); }
Pipeline存在原因
為了模塊分離?!绊?yè)面抽取”和“后處理、持久化”是爬蟲的兩個(gè)階段,將其分離開來(lái),一個(gè)是代碼結(jié)構(gòu)比較清晰,另一個(gè)是以后也可能將其處理過(guò)程分開,分開在獨(dú)立的線程以至于不同的機(jī)器執(zhí)行。
Pipeline的功能比較固定,更容易做成通用組件。每個(gè)頁(yè)面的抽取方式千變?nèi)f化,但是后續(xù)處理方式則比較固定,例如保存到文件、保存到數(shù)據(jù)庫(kù)這種操作,這些對(duì)所有頁(yè)面都是通用的。
常用Pipeline
WebMagic中就已經(jīng)提供了控制臺(tái)輸出、保存到文件、保存為JSON格式的文件幾種通用的Pipeline。
在WebMagic里,一個(gè)Spider可以有多個(gè)Pipeline,使用Spider.addPipeline()即可增加一個(gè)Pipeline。
public static void main(String[] args) { Spider.create(new GithubRepoPageProcessor()) // 初始訪問(wèn)url地址 .addUrl("https://github.com/code4craft") .addPipeline(new JsonFilePipeline("D:\webmagic\")) .addPipeline(new FilePipeline("D:\webmagic\")) //開啟5個(gè)線程抓取 .thread(5) //啟動(dòng)爬蟲 .run(); }
自定義Pipeline
基本Pipeline模式
在抽取的時(shí)候,將需要的數(shù)據(jù)保存為一個(gè)對(duì)象
public void process(Page page) { DemoData demoData=new DemoData(); demoData.setName("pipeline") page.putField("demoData", demoData); }
創(chuàng)建自定義Pipeline,在Pipeline中,只要使用即可
@Component public class MyDataPipeline implements Pipeline { @Autowired private DemoService demoService; @Override public void process(ResultItems resultItems, Task task) { // 獲取封裝好的數(shù)據(jù) DemoData demoData= resultItems.get("demoData"); if (demoData!= null) { // 把數(shù)據(jù)保存到數(shù)據(jù)庫(kù)中 this.demoService.save(demoData); } } }
注解模式
注解模式下,WebMagic內(nèi)置了一個(gè)PageModelPipeline
public interface PageModelPipeline<T> { // 傳入的是處理好的對(duì)象 public void process(T t, Task task); }
注解模式的入口是OOSpider,它繼承了Spider類,提供了特殊的創(chuàng)建方法。創(chuàng)建一個(gè)注解模式的爬蟲需要一個(gè)或者多個(gè)Model類,以及一個(gè)或者多個(gè)PageModelPipeline——定義處理結(jié)果的方式。
public static void main(String[] args) { OOSpider.create(Site.me().setSleepTime(1000) , new MyPipeline(), DemoData.class) //.addPageModel(new MyPipeline2(),DemoData2.class) .addUrl("https://github.com/code4craft").thread(5).run(); }
自定義MyPipeline類實(shí)現(xiàn)PageModelPipeline
@Component public class MyPipeline implements PageModelPipeline<DemoData> { @Autowired private DemoService demoService; @Override public void process(DemoData demoData, Task task) { if (demoData!= null) { // 把數(shù)據(jù)保存到數(shù)據(jù)庫(kù)中 this.demoService.save(demoData); } } }
推薦學(xué)習(xí):《java視頻教程》