1、網絡爬蟲基本介紹
2、java常見爬蟲框架介紹
3、WebCollector實戰
4、項目源碼下載
5、參考文章javascript
網絡爬蟲(又被稱爲網頁蜘蛛,網絡機器人,在社區中間,更常常的稱爲網頁追逐者),是一種按照必定的規則,自動地抓取萬維網信息的程序或者腳本。另一些不常使用的名字還有螞蟻、自動索引、模擬程序或者蠕蟲。css
爬蟲能夠爬取ajax信息麼?
網頁上有一些異步加載的數據,爬取這些數據有兩種方法:使用模擬瀏覽器(問題1中描述過了),或者分析ajax的http請求,本身生成ajax請求的url,獲取返回的數據。若是是本身生成ajax請求,使用開源爬蟲的意義在哪裏?實際上是要用開源爬蟲的線程池和URL管理功能(好比斷點爬取)。
若是我已經能夠生成我所須要的ajax請求(列表),如何用這些爬蟲來對這些請求進行爬取?
爬蟲每每都是設計成廣度遍歷或者深度遍歷的模式,去遍歷靜態或者動態頁面。爬取ajax信息屬於deep web(深網)的範疇,雖然大多數爬蟲都不直接支持。可是也能夠經過一些方法來完成。好比WebCollector使用廣度遍從來遍歷網站。爬蟲的第一輪爬取就是爬取種子集合(seeds)中的全部url。簡單來講,就是將生成的ajax請求做爲種子,放入爬蟲。用爬蟲對這些種子,進行深度爲1的廣度遍歷(默認就是廣度遍歷)。html
爬蟲支持多線程麼、爬蟲能用代理麼、爬蟲會爬取重複數據麼、爬蟲能爬取JS生成的信息麼?
能不能爬js生成的信息和爬蟲自己沒有太大關係。爬蟲主要是負責遍歷網站和下載頁面。爬js生成的信息和網頁信息抽取模塊有關,每每須要經過模擬瀏覽器(htmlunit,selenium)來完成。這些模擬瀏覽器,每每須要耗費不少的時間來處理一個頁面。因此一種策略就是,使用這些爬蟲來遍歷網站,遇到須要解析的頁面,就將網頁的相關信息提交給模擬瀏覽器,來完成JS生成信息的抽取。java
爬蟲怎麼保存網頁的信息?
有一些爬蟲,自帶一個模塊負責持久化。好比webmagic,有一個模塊叫pipeline。經過簡單地配置,能夠將爬蟲抽取到的信息,持久化到文件、數據庫等。還有一些爬蟲,並無直接給用戶提供數據持久化的模塊。好比crawler4j和webcollector。讓用戶本身在網頁處理模塊中添加提交數據庫的操做。至於使用pipeline這種模塊好很差,就和操做數據庫使用ORM好很差這個問題相似,取決於你的業務。linux
爬蟲怎麼爬取要登錄的網站?
這些開源爬蟲都支持在爬取時指定cookies,模擬登錄主要是靠cookies。至於cookies怎麼獲取,不是爬蟲管的事情。你能夠手動獲取、用http請求模擬登錄或者用模擬瀏覽器自動登錄獲取cookie。git
爬蟲怎麼抽取網頁的信息?
開源爬蟲通常都會集成網頁抽取工具。主要支持兩種規範:CSS SELECTOR和XPATH。至於哪一個好,這裏不評價。程序員
明明代碼寫對了,爬不到數據,是否是爬蟲有問題,換個爬蟲能解決麼?
若是代碼寫對了,又爬不到數據,換其餘爬蟲也是同樣爬不到。遇到這種狀況,要麼是網站把你封了,要麼是你爬的數據是javascript生成的。爬不到數據經過換爬蟲是不能解決的。github
爬蟲速度怎麼樣?
單機開源爬蟲的速度,基本均可以講本機的網速用到極限。爬蟲的速度慢,每每是由於用戶把線程數開少了、網速慢,或者在數據持久化時,和數據庫的交互速度慢。而這些東西,每每都是用戶的機器和二次開發的代碼決定的。web
爬蟲被網站封了怎麼辦?
爬蟲被網站封了,通常用多代理(隨機代理)就能夠解決。可是這些開源爬蟲通常沒有直接支持隨機代理ip的切換。ajax
(1)官方網站:http://nutch.apache.org/
(2)是否支持分佈式:是
(3)可擴展性:中。Apache Nutch並非一個可擴展性很強的爬蟲,它是一個專門爲搜索引擎定製的網絡爬蟲,雖然Apache Nutch具備一套強大的插件機制,但經過定製插件並不能修改爬蟲的遍歷算法、去重算法和爬取流程。
(4)適用性:Apache Nutch是爲搜索引擎定製的爬蟲,具備一套適合搜索引擎的URL維護機制(包括URL去重、網頁更新等),但這套機制並不適合目前大多數的精抽取業務(即結構化數據採集)。
(5)上手難易度:難。須要使用者熟悉網絡爬蟲原理、hadoop開發基礎及linux shell,且須要熟悉Apache Ant
(1)官方網站:https://github.com/CrawlScript/WebCollector
(2)可擴展性:強
(3)適用性:WebCollector適用於精抽取業務。
(4)上手難易度:簡單
(1)官方網站:http://git.oschina.net/flashsword20/webmagic
(2)是否支持分佈式:否
(3)可擴展性:強
(4)適用性:WebMagic適用於精抽取業務。
(5)上手難易度:簡單。
(1)官方網站:https://github.com/yasserg/crawler4j
(2) 是否支持分佈式:否
(3)可擴展性:低。Crawler4j其實是一個單機版的垂直爬蟲,其遍歷算法是一種相似泛爬的算法,雖然能夠添加一些限制,但仍不能知足目前大部分的精抽取業務。另外,Crawler4j並無提供定製http請求的接口,所以Crawler4j並不適用於須要定製http請求的爬取業務(例如模擬登錄、多代理切換)。
(4)上手難易度:簡單
傳統的網絡爬蟲傾向於整站下載,目的是將網站內容原樣下載到本地,數據的最小單元是單個網頁或文件。而WebCollector能夠經過設置爬取策略進行定向採集,並能夠抽取網頁中的結構化信息。
WebCollector是爬蟲框架,HttpClient是Http請求組件,Jsoup是網頁解析器(內置了Http請求功能)。
一些程序員在單線程中經過迭代或遞歸的方法調用HttpClient和Jsoup進行數據採集,這樣雖然也能夠完成任務,但存在兩個較大的問題:
(1)單線程速度慢,多線程爬蟲的速度遠超單線程爬蟲。
(2)須要本身編寫任務維護機制。這套機制裏面包括了URL去重、斷點爬取(即異常中斷處理)等功能。
WebCollector框架自帶了多線程和URL維護,用戶在編寫爬蟲時無需考慮線程池、URL去重和斷點爬取的問題。
WebCollector目前有單機版和Hadoop版(WebCollector-Hadoop),單機版可以處理千萬級別的URL,對於大部分的精數據採集任務,這已經足夠了。WebCollector-Hadoop可以處理的量級高於單機版,具體數量取決於集羣的規模。
WebCollector採用一種粗略的廣度遍歷,但這裏的遍歷與網站的拓撲樹結構沒有任何關係,用戶不須要在乎遍歷的方式。
網絡爬蟲會在訪問頁面時,從頁面中探索新的URL,繼續爬取。WebCollector爲探索新URL提供了兩種機制,自動解析和手動解析。
maven引入依賴
<dependencies> <dependency> <groupId>cn.edu.hfut.dmic.webcollector</groupId> <artifactId>WebCollector</artifactId> <version>2.73-alpha</version> </dependency> </dependencies>
自動解析
import cn.edu.hfut.dmic.webcollector.model.CrawlDatums; import cn.edu.hfut.dmic.webcollector.model.Page; import cn.edu.hfut.dmic.webcollector.plugin.berkeley.BreadthCrawler; public class AutoNewsCrawler extends BreadthCrawler { public AutoNewsCrawler(String crawlPath, boolean autoParse) { super(crawlPath, autoParse); this.addSeed("http://news.hfut.edu.cn/list-1-1.html");//種子頁面,起始頁面 //正則規則設置 尋找符合http://news.hfut.edu.cn/show-xxxxxxhtml的url this.addRegex("http://news.hfut.edu.cn/show-.*html"); this.addRegex("-.*\\.(jpg|png|gif).*"); //不要爬取包含 #的URL this.addRegex("-.*#.*"); setThreads(50);//線程數 getConf().setTopN(100);//設置每次迭代中爬取數量的上限 //設置是否爲斷點爬取,若是設置爲false,任務啓動前會清空歷史數據。 //若是設置爲true,會在已有crawlPath(構造函數的第一個參數)的基礎上繼 //續爬取。對於耗時較長的任務,極可能須要中途中斷爬蟲,也有可能遇到 //死機、斷電等異常狀況,使用斷點爬取模式,能夠保證爬蟲不受這些因素 //的影響,爬蟲能夠在人爲中斷、死機、斷電等狀況出現後,繼續之前的任務 //進行爬取。斷點爬取默認爲false*/ // setResumable(true); } /* visit函數定製訪問每一個頁面時所需進行的操做 */ @Override public void visit(Page page, CrawlDatums next) { String url = page.url(); //若是頁面地址如何咱們要求 if (page.matchUrl("http://news.hfut.edu.cn/show-.*html")) { String title = page.select("div[id=Article]>h2").first().text();//獲取url標題 String content = page.selectText("div#artibody"); System.out.println("URL:\n" + url);//地址 System.out.println("title:\n" + title);//標題 System.out.println("content:\n" + content);//內容 /*若是你想添加新的爬取任務,能夠向next中添加爬取任務, 這就是上文中提到的手動解析*/ /*WebCollector會自動去掉重複的任務(經過任務的key,默認是URL), 所以在編寫爬蟲時不須要考慮去重問題,加入重複的URL不會致使重複爬取*/ /*若是autoParse是true(構造函數的第二個參數),爬蟲會自動抽取網頁中符合正則規則的URL, 做爲後續任務,固然,爬蟲會去掉重複的URL,不會爬取歷史中爬取過的URL。 autoParse爲true即開啓自動解析機制*/ //next.add("http://xxxxxx.com"); } } public static void main(String[] args) throws Exception { AutoNewsCrawler crawler = new AutoNewsCrawler("crawl", true); crawler.start(4);//啓動爬蟲 } }
運行接入以下所示:
手動解析
import cn.edu.hfut.dmic.webcollector.model.CrawlDatums; import cn.edu.hfut.dmic.webcollector.model.Page; import cn.edu.hfut.dmic.webcollector.plugin.berkeley.BreadthCrawler; public class ManualNewsCrawler extends BreadthCrawler { public ManualNewsCrawler(String crawlPath, boolean autoParse) { super(crawlPath, autoParse); /*add 10 start pages and set their type to "list" "list" is not a reserved word, you can use other string instead */ for(int i = 1; i <= 10; i++) { this.addSeed("http://news.hfut.edu.cn/list-1-" + i + ".html", "list");//種子頁面,起始頁面 } setThreads(50);//線程數 getConf().setTopN(100);//設置每次迭代中爬取數量的上限 //設置是否爲斷點爬取,若是設置爲false,任務啓動前會清空歷史數據。 //若是設置爲true,會在已有crawlPath(構造函數的第一個參數)的基礎上繼 //續爬取。對於耗時較長的任務,極可能須要中途中斷爬蟲,也有可能遇到 //死機、斷電等異常狀況,使用斷點爬取模式,能夠保證爬蟲不受這些因素 //的影響,爬蟲能夠在人爲中斷、死機、斷電等狀況出現後,繼續之前的任務 //進行爬取。斷點爬取默認爲false*/ // setResumable(true); } /* visit函數定製訪問每一個頁面時所需進行的操做 * */ @Override public void visit(Page page, CrawlDatums next) { String url = page.url(); if (page.matchType("list")) { next.add(page.links("div[class=' col-lg-8 '] li>a")).type("content"); }else if(page.matchType("content")) { /*if type is "content"*/ /*extract title and content of news by css selector*/ String title = page.select("div[id=Article]>h2").first().text(); String content = page.selectText("div#artibody", 0); //read title_prefix and content_length_limit from configuration title = getConf().getString("title_prefix") + title; content = content.substring(0, getConf().getInteger("content_length_limit")); System.out.println("URL:\n" + url); System.out.println("title:\n" + title); System.out.println("content:\n" + content); } } public static void main(String[] args) throws Exception { ManualNewsCrawler crawler = new ManualNewsCrawler("crawl", false); crawler.getConf().setExecuteInterval(5000); crawler.getConf().set("title_prefix","PREFIX_"); crawler.getConf().set("content_length_limit", 20); crawler.start(4);//啓動爬蟲 } }
運行結果以下圖所示:
連接:https://pan.baidu.com/s/10Ze9xloOpVqmlBOj97XNaQ
提取碼:ig45