站長資訊網
        最全最豐富的資訊網站

        Java爬蟲框架之WebMagic的學習總結

        本篇文章給大家帶來了關于java的相關知識,其中主要介紹了關于WebMagic的相關內容,WebMagic是一個簡單靈活的Java爬蟲框架,分為核心和擴展兩部分,下面一起來看一下,希望對大家有幫助。

        Java爬蟲框架之WebMagic的學習總結

        程序員必備接口測試調試工具:立即使用
        Apipost = Postman + Swagger + Mock + Jmeter
        Api設計、調試、文檔、自動化測試工具
        后端、前端、測試,同時在線協作,內容實時同步

        推薦學習:《java視頻教程》

        概述

        WebMagic是一個簡單靈活的Java爬蟲框架。基于WebMagic,可以快速開發出一個高效、易維護的爬蟲。

        WebMagic分為核心和擴展兩部分。核心部分(webmagic-core)是一個精簡的、模塊化的爬蟲實現,而擴展部分則包括一些便利的、實用性的功能。

        特性

        簡單的API,可快速上手

        模塊化的結構,可輕松擴展

        提供多線程和分布式支持

        架構

        WebMagic的結構分為Downloader、PageProcessor、Scheduler、Pipeline四大組件,并由Spider將它們彼此組織起來。

        四大組件對應爬蟲生命周期中的下載、處理、管理和持久化等功能。WebMagic的設計參考了Scapy,實現方式更加Java化一些。

        Spider則將這幾個組件組織起來,讓它們可以互相交互,流程化的執行,可以認為Spider是一個大的容器,它也是WebMagic邏輯的核心。

        Java爬蟲框架之WebMagic的學習總結

        四大組件

        Downloader

        Downloader負責從互聯網上下載頁面,以便后續處理。WebMagic默認使用了Apache HttpClient作為下載工具。

        PageProcessor

        PageProcessor負責解析頁面,抽取有用信息,以及發現新的鏈接。WebMagic使用Jsoup作為HTML解析工具,并基于其開發了解析XPath的工具Xsoup。

        在這四個組件中,PageProcessor對于每個站點每個頁面都不一樣,是需要使用者定制的部分。

        Scheduler

        Scheduler負責管理待抓取的URL,以及一些去重的工作。WebMagic默認提供了JDK的內存隊列來管理URL,并用集合來進行去重。也支持使用Redis進行分布式管理。

        Pipeline

        Pipeline負責抽取結果的處理,包括計算、持久化到文件、數據庫等。WebMagic默認提供了“輸出到控制臺”和“保存到文件”兩種結果處理方案。

        Pipeline定義了結果保存的方式,如果你要保存到指定數據庫,則需要編寫對應的Pipeline。對于一類需求一般只需編寫一個Pipeline。

        數據流轉對象

        Request

        Request是對URL地址的一層封裝,一個Request對應一個URL地址。它是PageProcessor與Downloader交互的載體,也是PageProcessor控制Downloader唯一方式。

        除了URL本身外,它還包含一個Key-Value結構的字段extra。你可以在extra中保存一些特殊的屬性,然后在其他地方讀取,以完成不同的功能。例如附加上一個頁面的一些信息等。

        Page

        Page代表了從Downloader下載到的一個頁面——可能是HTML,也可能是JSON或者其他文本格式的內容。

        Page是WebMagic抽取過程的核心對象,它提供一些方法可供抽取、結果保存等。

        ResultItems

        ResultItems相當于一個Map,它保存PageProcessor處理的結果,供Pipeline使用。它的API與Map很類似,值得注意的是它有一個字段skip,若設置為true,則不應被Pipeline處理。

        控制爬蟲運轉的引擎Spider

        Spider是WebMagic內部流程的核心。Downloader、PageProcessor、Scheduler、Pipeline都是Spider的一個屬性,這些屬性是可以自由設置的,通過設置這個屬性可以實現不同的功能。Spider也是WebMagic操作的入口,它封裝了爬蟲的創建、啟動、停止、多線程等功能。

        以下是一個設置各個組件,并且設置多線程和啟動的例子。

        public static void main(String[] args) {     Spider.create(new GithubRepoPageProcessor())             //從https://github.com/code4craft開始抓                 .addUrl("https://github.com/code4craft")             //設置Scheduler,使用Redis來管理URL隊列             .setScheduler(new RedisScheduler("localhost"))             //設置Pipeline,將結果以json方式保存到文件             .addPipeline(new JsonFilePipeline("D:\data\webmagic"))             //開啟5個線程同時執行             .thread(5)             //啟動爬蟲             .run(); }
        登錄后復制

        WebMagic的基本使用

        添加WebMagic的核心與擴展依賴

              <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>
        登錄后復制

        爬蟲實現

        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()             //設置編碼             .setCharset("utf8")             //設置超時時間,單位是ms毫秒             .setTimeOut(10000)             //設置重試的間隔時間             .setRetrySleepTime(3000)             //設置重試次數             .setSleepTime(3);     public Site getSite() {         return site;     }     public static void main(String[] args) {         Spider.create(new MyJobProcessor())                 //初始訪問url地址                 .addUrl("http://www.baidu.com")                 .run();     } }
        登錄后復制

        get page: http://www.baidu.com title:<input type="submit" id="su" value="百度一下" class="bg s_btn">
        登錄后復制

        爬蟲的編寫過程

        實現PageProcessor

        PageProcessor的定制分為三個部分,分別是爬蟲的配置、頁面元素的抽取和鏈接的發現

        爬蟲配置

        爬蟲的配置,包括編碼、抓取間隔、超時時間、重試次數等,也包括一些模擬的參數,例如User Agent、cookie,以及代理的設置。

            private Site site = Site.me()             //設置編碼             .setCharset("utf8")             //設置超時時間,單位是ms毫秒             .setTimeOut(10000)             //設置重試的間隔時間             .setRetrySleepTime(3000)             //設置重試次數             .setSleepTime(3);
        登錄后復制

        抽取頁面元素

        頁面元素的抽取是爬蟲的核心部分:對于下載到的Html頁面,如何從中抽取到想要的信息?

        WebMagic主要使用三種抽取技術:XPath、正則表達式和CSS選擇器。對于JSON格式的內容,可使用JsonPath進行解析

        XPath

        獲取屬性class=myClass的div標簽,里面的h1標簽的內容

        page.getHtml().xpath("//div[@class=myClass]/h1/text()")
        登錄后復制

        CSS選擇器

        CSS選擇器是與XPath類似的語言。Jsoup的選擇器比XPath寫起來要簡單一些,但是如果寫復雜一點的抽取規則,就相對要麻煩一點。

        獲取屬性class為myClass的div標簽下的直接子元素h1標簽

        page.getHtml().css("div.mt>h1").toString()
        登錄后復制

        可使用:nth-child(n)選擇第幾個元素,但是注意:需要使用直接子元素才可以選擇第幾個元素

        如: 選擇第一個元素

        page.getHtml().css("div#myId > ul > li:nth-child(1) a").toString()
        登錄后復制

        正則表達式

        正則表達式則是一種通用的文本抽取語言。在這里一般用于獲取url地址。

        匹配所有https://github.com/code4craft/webmagic這樣的鏈接。

        page.addTargetRequests(page.getHtml().links().regex("(https://github\.com/\w+/\w+)").all());
        登錄后復制

        登錄后復制

        JsonPath

        JsonPath是于XPath很類似的一個語言,它用于從Json中快速定位一條內容。

        鏈接的發現

        一個站點的頁面是很多的,一開始不可能全部列舉出來,于是如何發現后續的鏈接,是一個爬蟲不可缺少的一部分。

        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+這個正則表達式的鏈接

        page.addTargetRequests()則將這些鏈接加入到待抓取的隊列中去。

        Selectable抽取元素

        Selectable相關的抽取元素鏈式API是WebMagic的一個核心功能。使用Selectable接口,就可以直接完成頁面元素的鏈式抽取,也無需去關心抽取的細節。

        上述page.getHtml()返回的是一個Html對象,它實現了Selectable接口。這個接口包含一些重要的方法,將它分為兩類:抽取部分和獲取結果部分。

        抽取部分API

        抽取部分API返回的都是一個Selectable接口,是支持鏈式調用的。

        Java爬蟲框架之WebMagic的學習總結

        獲取結果的API

        當鏈式調用結束時,一般都想要拿到一個字符串類型的結果。這時候就需要用到獲取結果的API了。

        一條抽取規則,無論是XPath、CSS選擇器或者正則表達式,總有可能抽取到多條元素。WebMagic對這些進行了統一,可以通過不同的API獲取到一個或者多個元素。

        Java爬蟲框架之WebMagic的學習總結

        注意:當有多條數據的時候,使用get()和toString()都是獲取第一個url地址。

        使用Pipeline保存結果

        如何將抓取的結果保存下來?WebMagic用于保存結果的組件叫做Pipeline。

        例如通過“控制臺輸出結果”這件事也是通過一個內置的Pipeline完成的,它叫做ConsolePipeline。

        想要把結果用Json的格式保存下來,只需要將Pipeline的實現換成"JsonFilePipeline"就可以了。

        想要把結果用保存到文件中,只將Pipeline的實現換成"FilePipeline"就可以了。

        public static void main(String[] args) {     Spider.create(new GithubRepoPageProcessor())             // 初始訪問url地址             .addUrl("https://github.com/code4craft")             .addPipeline(new JsonFilePipeline("D:\webmagic\"))             //.addPipeline(new FilePipeline("D:\webmagic\"))             //開啟5個線程抓取             .thread(5)             //啟動爬蟲             .run(); }
        登錄后復制

        爬蟲的配置、啟動和終止

        Spider啟動入口

        Spider是爬蟲啟動的入口。在啟動爬蟲之前,需要使用一個PageProcessor創建一個Spider對象,然后使用run()進行啟動。同時Spider的其他組件(Downloader、Scheduler、Pipeline)都可以通過set方法來進行設置。

        Java爬蟲框架之WebMagic的學習總結

        Site爬蟲配置

        對站點本身的一些配置信息,例如編碼、HTTP頭、超時時間、重試策略等、代理等,都可以通過設置Site對象來進行配置。

        Java爬蟲框架之WebMagic的學習總結

        rivate Site site = Site.me()         .setCharset("UTF-8")//編碼         .setSleepTime(1)//抓取間隔時間         .setTimeOut(1000*10)//超時時間         .setRetrySleepTime(3000)//重試時間         .setRetryTimes(3);//重試次數
        登錄后復制

        配置代理

        代理服務器

        有些網站不允許爬蟲進行數據爬取,因為會加大服務器的壓力。其中一種最有效的方式是通過ip+時間進行鑒別,因為正常人不可能短時間開啟太多的頁面,發起太多的請求。

        使用WebMagic可以設置爬取數據的時間,但是會大大降低爬取數據的效率。如果ip被禁了,就有必要使用代理服務器來爬取數據。

        代理(Proxy),也稱網絡代理,是一種特殊的網絡服務,允許一個網絡終端(一般為客戶端)通過這個服務與另一個網絡終端(一般為服務器)進行非直接的連接。

        提供代理服務的電腦系統或其它類型的網絡終端稱為代理服務器(Proxy Server)。一個完整的代理請求過程為:客戶端首先與代理服務器創建連接,接著根據代理服務器所使用的代理協議,請求對目標服務器創建連接、或者獲得目標服務器的指定資源。

        使用代理服務器

        WebMagic使用的代理對象是APIProxyProvider。代理由HttpClientDownloader設置。

        Java爬蟲框架之WebMagic的學習總結

        ProxyProvider有一個默認實現:SimpleProxyProvider。它是一個基于簡單Round-Robin的、沒有失敗檢查的ProxyProvider。可以配置任意個候選代理,每次會按順序挑選一個代理使用。它適合用在自己搭建的比較穩定的代理的場景。

        如果需要根據實際使用情況對代理服務器進行管理(例如校驗是否可用,定期清理、添加代理服務器等),只需要自己實現APIProxyProvider

        在Spider啟動入口處配置代理

            public void Process() {         // 創建下載器Downloader         HttpClientDownloader httpClientDownloader = new HttpClientDownloader();         // 給下載器設置代理服務器信息         Proxy proxy = new Proxy("183.166.148.28", 64305);         httpClientDownloader.setProxyProvider(SimpleProxyProvider.from(proxy));         Spider.create(new ProxyTest())                 // 淘寶獲取本機IP地址                 .addUrl("https://www.taobao.com/help/getip.php")                 .setDownloader(httpClientDownloader)                 .run();     }
        登錄后復制

        Scheduler組件

        概述

        Scheduler是WebMagic中進行URL管理的組件。

        Scheduler包括兩個作用:

        對待抓取的URL隊列進行管理。

        對已抓取的URL進行去重。

        WebMagic內置了幾個常用的Scheduler。如果只是在本地執行規模比較小的爬蟲,那么基本無需定制Scheduler

        Java爬蟲框架之WebMagic的學習總結

        對Scheduler的內部實現進行了重構,去重部分被單獨抽象成了一個接口:DuplicateRemover,從而可以為同一個Scheduler選擇不同的去重方式,以適應不同的需要,目前提供了兩種去重方式。

        Java爬蟲框架之WebMagic的學習總結

        所有默認的Scheduler都使用HashSetDuplicateRemover來進行去重,除了RedisScheduler。

        RedisScheduler是使用Redis的set進行去重,其他的Scheduler默認都使用HashSetDuplicateRemover來進行去重。

        如果URL較多,使用HashSetDuplicateRemover會比較占用內存,可嘗試BloomFilterDuplicateRemover

        使用布隆過濾器

        布隆過濾器 (Bloom Filter)是一種space efficient的概率型數據結構,用于判斷一個元素是否在集合中。在垃圾郵件過濾的黑白名單方法、爬蟲(Crawler)的網址判重模塊中等等經常被用到。

        哈希表也能用于判斷元素是否在集合中,但是布隆過濾器只需要哈希表的1/8或1/4的空間復雜度就能完成同樣的問題。

        布隆過濾器可以插入元素,但不可以刪除已有元素。其中的元素越多,誤報率越大,但是漏報是不可能的。

        原理:

        布隆過濾器需要的是一個位數組(和位圖類似)和K個映射函數(和Hash表類似),在初始狀態時,對于長度為m的位數組array,它的所有位被置0。

        如果要使用BloomFilter,必須要加入以下依賴:

         <!--WebMagic對布隆過濾器的支持-->         <dependency>             <groupId>com.google.guava</groupId>             <artifactId>guava</artifactId>             <version>31.1-jre</version>         </dependency>
        登錄后復制

        添加布隆過濾器

        public static void main(String[] args) {     Spider.create(new JobProcessor())             //初始訪問url地址             .addUrl("https://github.com/code4craft")             .addPipeline(new FilePipeline("D:/webmagic/"))             .setScheduler(new QueueScheduler()             .setDuplicateRemover(new BloomFilterDuplicateRemover(10000000))) //參數設置需要對多少條數據去重             .thread(1)//設置線程數             .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;     }
        登錄后復制

        打開布隆過濾器BloomFilterDuplicateRemover,在isDuplicate方法處可斷點驗證

        Java爬蟲框架之WebMagic的學習總結

        對比

        HashSet

        使用java中的HashSet不能重復的特點去重。優點是容易理解。使用方便。缺點:占用內存大,性能較低。

        Redis去重

        使用Redis的set進行去重。優點是速度快(Redis本身速度就很快),而且去重不會占用爬蟲服務器的資源,可以處理更大數據量的數據爬取。缺點:需要準備Redis服務器,增加開發和使用成本。

        布隆過濾器(BloomFilter)

        使用布隆過濾器也可以實現去重。優點是占用的內存要比使用HashSet要小的多,也適合大量數據的去重操作。缺點:有誤判的可能。沒有重復可能會判定重復,但是重復數據一定會判定重復。

        布隆過濾器的實現

        public class BloomFilter {     /**      * BitSet初始分配2^24個bit      */     private static final int DEFAULT_SIZE = 1 << 24;     /**      * 不同哈希函數的種子,一般應取質數      */     private static final int[] seeds = new int[]{5, 7, 11, 13, 31, 37};     private BitSet bits = new BitSet(DEFAULT_SIZE);     /**      * 哈希函數對象      */     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標記到bits中      *      * @param str      */     public void add(String str) {         for (SimpleHash f : func) {             bits.set(f.hash(str), true);         }     }     /**      * 判斷是否已經被bits標記      *      * @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;     }     /**      * 哈希函數類      */     public static class SimpleHash {         private int cap;         private int seed;         public SimpleHash(int cap, int seed) {             this.cap = cap;             this.seed = seed;         }         /**          * hash函數,采用簡單的加權和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是抽取結束后,進行處理的部分,它主要用于抽取結果的保存,也可以定制Pileline可以實現一些通用的功能。

        Pipeline是將PageProcessor抽取的結果,繼續進行處理,在Pipeline中完成的功能,基本上也可以直接在PageProcessor實現。

        Pipeline的接口定義

        public interface Pipeline {     // ResultItems保存了抽取結果,它是一個Map結構     // 在page.putField(key,value)中保存的數據,可以通過ResultItems.get(key)獲取     public void process(ResultItems resultItems, Task task); }
        登錄后復制

        Pipeline存在原因

        為了模塊分離。“頁面抽取”和“后處理、持久化”是爬蟲的兩個階段,將其分離開來,一個是代碼結構比較清晰,另一個是以后也可能將其處理過程分開,分開在獨立的線程以至于不同的機器執行。

        Pipeline的功能比較固定,更容易做成通用組件。每個頁面的抽取方式千變萬化,但是后續處理方式則比較固定,例如保存到文件、保存到數據庫這種操作,這些對所有頁面都是通用的。

        常用Pipeline

        WebMagic中就已經提供了控制臺輸出、保存到文件、保存為JSON格式的文件幾種通用的Pipeline。

        Java爬蟲框架之WebMagic的學習總結

        在WebMagic里,一個Spider可以有多個Pipeline,使用Spider.addPipeline()即可增加一個Pipeline。

        public static void main(String[] args) {     Spider.create(new GithubRepoPageProcessor())             // 初始訪問url地址             .addUrl("https://github.com/code4craft")             .addPipeline(new JsonFilePipeline("D:\webmagic\"))             .addPipeline(new FilePipeline("D:\webmagic\"))             //開啟5個線程抓取             .thread(5)             //啟動爬蟲             .run(); }
        登錄后復制

        自定義Pipeline

        基本Pipeline模式

        在抽取的時候,將需要的數據保存為一個對象

        public void process(Page page) { DemoData  demoData=new DemoData(); demoData.setName("pipeline")         page.putField("demoData", demoData); }
        登錄后復制

        創建自定義Pipeline,在Pipeline中,只要使用即可

        @Component public class MyDataPipeline  implements Pipeline {     @Autowired     private DemoService demoService;     @Override     public void process(ResultItems resultItems, Task task) {         // 獲取封裝好的數據         DemoData demoData= resultItems.get("demoData");         if (demoData!= null) {             // 把數據保存到數據庫中             this.demoService.save(demoData);         }     } }
        登錄后復制

        注解模式

        注解模式下,WebMagic內置了一個PageModelPipeline

        public interface PageModelPipeline<T> {     // 傳入的是處理好的對象     public void process(T t, Task task); }
        登錄后復制

        注解模式的入口是OOSpider,它繼承了Spider類,提供了特殊的創建方法。創建一個注解模式的爬蟲需要一個或者多個Model類,以及一個或者多個PageModelPipeline——定義處理結果的方式。

         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類實現PageModelPipeline

        @Component public class MyPipeline implements PageModelPipeline<DemoData> {     @Autowired     private DemoService demoService;     @Override     public void process(DemoData demoData, Task task) {         if (demoData!= null) {             // 把數據保存到數據庫中             this.demoService.save(demoData);         }     } }
        登錄后復制

        推薦學習:《java視頻教程》

        贊(0)
        分享到: 更多 (0)
        網站地圖   滬ICP備18035694號-2    滬公網安備31011702889846號
        主站蜘蛛池模板: 国产AⅤ精品一区二区三区久久| 国产精品无套内射迪丽热巴| 亚洲国产精品无码AAA片| 国产精品你懂的| 亚洲精品乱码久久久久久蜜桃图片| 66精品综合久久久久久久| 精品一区二区三区东京热| 欧美精品亚洲精品日韩精品| 久久99精品国产| 国产精品原创巨作av女教师| 亚洲爆乳精品无码一区二区 | 93精91精品国产综合久久香蕉| 久久狠狠高潮亚洲精品| 亚洲а∨天堂久久精品9966| 国产精品主播一区二区| 精品久久久久久| 国产精品三级在线观看无码| 亚洲日韩精品无码一区二区三区| 欧美激情视频精品一区二区| 91人前露出精品国产| 精品无人区麻豆乱码1区2区| 国产精品特级毛片一区二区三区 | 久久九九久精品国产| 99在线精品免费视频| 久久国产亚洲精品麻豆| 国产精品欧美一区二区三区不卡| 国产亚洲精品自在久久| 亚洲国产午夜中文字幕精品黄网站| 国产成人精品无码免费看| 嫩草伊人久久精品少妇AV| 亚洲日韩精品A∨片无码| 无码精品第一页| 久久人人超碰精品CAOPOREN | 国产精品成熟老女人视频| 久久精品国产精品亚洲毛片| 亚洲国产精品无码av| 日韩精品人妻系列无码专区 | 性欧洲精品videos| 亚洲AV无码久久精品蜜桃| 亚洲精品成人片在线播放| 亚洲日韩精品A∨片无码|