摘要:爬蟲又一個爬蟲實現(xiàn)原文簡介小強當(dāng)時不知道為啥選了這么個名字,又長又難記,導(dǎo)致編碼的過程中因為單詞的拼寫問題耽誤了好長時間。我是一個小強爬蟲線程數(shù)健壯說到健壯,這里主要體現(xiàn)在以下幾個方面應(yīng)對封鎖這里我們使用動態(tài)代理來解決這個問題。
cockroach 爬蟲:又一個 java 爬蟲實現(xiàn)
原文
簡介cockroach[小強] 當(dāng)時不知道為啥選了這么個名字,又長又難記,導(dǎo)致編碼的過程中因為單詞的拼寫問題耽誤了好長時間。
這個項目算是我的又一個坑吧,算起來挖的坑多了去了,多一個不多少一個不少。
一個小巧、靈活、健壯的爬蟲框架,暫且叫做框架吧。
簡單到什么程度呢,幾句話就可以創(chuàng)建一個爬蟲。
環(huán)境java8 程序中用到了一些 java8 的新特性
maven
com.github.zhangyingwei cockroach 1.0.5-Beta
如果哪天我忘了更新文檔了,一定要記住使用最新的版本,最新的版本,新的版本,版本,本。
下面就逐點介紹一下:
小巧小巧主要體現(xiàn)在兩個方面
體積小 (打包之后整個 jar 包只有 70k 多一點,所以完全擔(dān)得起小巧兩個字)
開發(fā)代碼量?。ɑ诒究蚣荛_發(fā)一個爬蟲需要的工作量可以說是非常小。這個在下邊的文檔中會有體現(xiàn))
實例在項目中新建一個測試類 App.java 并新建 main 方法。
public static void main(String[] args){ CockroachConfig config = new CockroachConfig() .setAppName("我是一個小強") .setThread(2); //爬蟲線程數(shù) CockroachContext context = new CockroachContext(config); TaskQueue queue = TaskQueue.of(); context.start(queue); // 以上就是一個完整的爬蟲,下邊的代碼相當(dāng)于一個生產(chǎn)者,往隊列里邊寫任務(wù),一旦寫入任務(wù),爬蟲就會對任務(wù)進行爬取 new Thread(() -> { int i = 0; while(true){ i++; try { Thread.sleep(1000); String url = "http://www.xicidaili.com/wt/"+i; System.out.println(url); queue.push(new Task(url)); } catch (InterruptedException e) { e.printStackTrace(); } if (i > 1000) { break; } } }).start(); }靈活
那靈活又體現(xiàn)在什么方面呢
可以自定義 http 客戶端(可選
,默認使用 okhttp3)
可以自定義結(jié)果的處理 (可選,默認使用打印處理器)
自定義 http 客戶端首先我們嘗試一下自定義客戶端
public class SelfHttpClient implements HttpClient { public HttpClient setProxy(HttpProxy proxy){ //設(shè)置代理實現(xiàn)方法 } public TaskResponse doGet(Task task) throws Exception{ // get 請求實現(xiàn)方法 } public HttpClient proxy(){ // 應(yīng)用代理到 http 客戶端 方法 } public TaskResponse doPost(Task task) throws Exception{ // post 請求實現(xiàn)方法 } public HttpClient setCookie(String cookie){ // 設(shè)置 cookie 實現(xiàn)方法 } public HttpClient setHttpHeader(MaphttpHeader){ // 設(shè)置 header 實現(xiàn)方法 } }
應(yīng)用自定義 http 客戶端到爬蟲
CockroachConfig config = new CockroachConfig() .setAppName("我是一個小強") .setThread(2) //爬蟲線程數(shù) .setHttpClient(SelfHttpClient.class)
PS:上邊這一塊目前處于待定狀態(tài)
自定義結(jié)果處理類自定義結(jié)果處理類
public class SelfStore implements IStore { @Override public void store(TaskResponse response) { System.out.println(response.getContent()); } }
這里簡單的將結(jié)果打印了出來,在實際應(yīng)用中,我們可以保存到數(shù)據(jù)庫或者保存到文件中等等。值得一說的是,如果結(jié)果是 html 網(wǎng)頁文本的話,我們還提供了 select("css選擇器") 來對結(jié)果文本進行處理。
應(yīng)用自定義 store 客戶端到爬蟲
CockroachConfig config = new CockroachConfig() .setAppName("我是一個小強") .setThread(2) //爬蟲線程數(shù) .setHttpClient(SelfHttpClient.class) .setStore(SelfStore.class);自定義錯誤處理類
當(dāng) http 請求網(wǎng)頁出現(xiàn)錯誤的時候會統(tǒng)一定位到錯誤處理類,如果沒有自定義錯誤處理類,系統(tǒng)會默認使用 DefaultTaskErrorHandler ,此處理類會吧錯誤信息打印出來。具體實現(xiàn)代碼如下。
public class DefaultTaskErrorHandler implements ITaskErrorHandler { private Logger logger = Logger.getLogger(DefaultTaskErrorHandler.class); @Override public void error(Task task,String message) { logger.info("task error: "+message); } }
如果需要自定義錯誤處理類,可以仿照以上代碼,實現(xiàn) ITaskErrorHandler 接口,在 error 方法中實現(xiàn)自己的處理邏輯。
在自定義錯誤處理類之后,我們需要把自定義類應(yīng)用到爬蟲。
CockroachConfig config = new CockroachConfig() .setAppName("我是一個小強") .setThread(2) //爬蟲線程數(shù) .setHttpClient(SelfHttpClient.class) .setStore(SelfStore.class) .setTaskErrorHandler(SelfTaskErrorHandler.class);健壯
說到健壯,這里主要體現(xiàn)在以下幾個方面:
應(yīng)對IP封鎖
這里我們使用動態(tài)代理來解決這個問題。
動態(tài)代理的使用CockroachConfig config = new CockroachConfig() .setAppName("我是一個小強") .setThread(2) //爬蟲線程數(shù) .setHttpClient(SelfHttpClient.class) .setProxys("100.100.100.100:8888,101.101.101.101:8888")
如上所示,我們可以設(shè)置若干個代理 ip,最終將所有代理 ip 生成一個代理池,在爬蟲請求之前,我們會從代理池中隨機抽取一個 ip 做代理。
應(yīng)對 http 請求中的 user-agent 問題
程序中實現(xiàn)了一個 user-agent 池,每次請求都會隨機取出一個 user-agent 使用,目前在程序中集成了 17 種 user-agent,后續(xù)會考慮把這塊開放出來到配置中,自定義配置(有沒有意義呢?)。
程序中的異常處理問題
目前在異常處理這塊,本身也不是非常擅長,已經(jīng)盡力把異常控制在一個可控的范圍內(nèi),程序中定義了很多自定義異常,這里沒有什么發(fā)言權(quán),就不細說了,各位要是有意見建議,歡迎拍磚。
所謂深度爬取程序中并沒有現(xiàn)成的深度爬取實現(xiàn),是因為一般情況下我并不覺得深度爬取有什么卵用,但是也不是沒有為深度爬取留出來一席之地。我們可以自己提取出頁面中的鏈接并加入到任務(wù)隊列中。以達到深度爬取的效果。
public class DemoStore implements IStore { private String id = NameUtils.name(DemoStore.class); public DemoStore() throws IOException {} @Override public void store(TaskResponse response) throws IOException { List注解支持urls = response.select("a").stream().map(element -> element.attr("href")).collect(Collectors.toList()); try { response.getQueue().push(urls); } catch (Exception e) { e.printStackTrace(); } } }
最近忙里偷閑增加了注解支持,那么在使用注解之后,一個爬蟲是什么樣的呢?
@EnableAutoConfiguration @AppName("hello spider") @Store(PrintStore.class) @AutoClose(true) @ThreadConfig(num = 1) @CookieConfig("asdfasdfasdfasdfasfasdfa") @HttpHeaderConfig({ "key1=value1", "key2=value2" }) @ProxyConfig("1.1.1.1,2.2.2.2") public class CockroachApplicationTest { public static void main(String[] args) throws Exception { TaskQueue queue = TaskQueue.of(); queue.push(new Task("http://blog.zhangyingwei.com")); CockroachApplication.run(CockroachApplicationTest.class,queue); } }
如上就是基本上所有注解的演示,那么拋開演示的部分,如果真的只是做一個demo,需要怎么寫呢?
@EnableAutoConfiguration public class CockroachApplicationTest { public static void main(String[] args) throws Exception { TaskQueue queue = TaskQueue.of(); queue.push(new Task("http://blog.zhangyingwei.com")); CockroachApplication.run(CockroachApplicationTest.class,queue); } }
沒錯,就是這么簡單。這個爬蟲就是爬取 http://blog.zhangyingwei.com 這個頁面的內(nèi)容并將結(jié)果打印出來。
在爬蟲結(jié)果處理這個問題上,程序中默認使用 PringStore 這個類將所有結(jié)果打印出來。
最近做了一個工作職位的爬蟲,在爬拉鉤的時候遇到一個問題。需要登錄才能爬取,這個當(dāng)然配置 cookie 就能解決,但是拉鉤的 cookie 里邊做了防爬蟲驗證。cookie 里邊有一個時間需要動態(tài)變化。所以就產(chǎn)生了這個功能。
這個功能使用起來如下:
Cookie 生成器@CookieConfig(cookieGenerator = CookieGeneratorTest.class)
/** * Created by zhangyw on 2017/12/19. */ public class CookieGeneratorTest implements StringGenerator { @Override public String get(Task task) { String cookie = "v="+ UUID.randomUUID().toString(); System.out.println(cookie); return cookie; } }
在每次發(fā)生 http 請求之前,程序都會調(diào)用 Generator 的 get 方法。獲取到本次的 cookie 值,并附加到 http 請求頭中。
Header 生成器由于程序中需要的 header 是 map 類型的數(shù)據(jù),所以 header 生成器如下:
@HttpHeaderConfig(headerGenerator = HeaderGeneratorTest.class)
/** * Created by zhangyw on 2017/12/19. */ public class HeaderGeneratorTest implements MapGenerator { private Map headers = new HashMap(); @Override public Map get(Task task) { return headers; } }
以上就是目前所有的生成器,可以看到生成器中傳入了 task 對象,這里是為了在爬蟲應(yīng)對不同的地址的時候使用不同的 cookie/header 。
算了還是舉個栗子吧:
/** * Created by zhangyw on 2017/12/19. */ public class HeaderGeneratorTest implements MapGenerator { private Map headers = new HashMap(); @Override public Map get(Task task) { if ("jobs.lagou".equals(task.getGroup())) { header.put("key","value"); return headers; } else { return null; } } }
OK,到此為止,就啰嗦這么多了。
最后,各位大大如果覺得不討厭的話,來個 start 唄。
https://github.com/zhangyingwei/cockroach
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/70865.html
摘要:文章目錄前言爬取分析視頻教學(xué)成果展示福利入門到就業(yè)學(xué)習(xí)路線規(guī)劃小白快速入門爬蟲路線前言皮皮蝦一個沙雕而又有趣的憨憨少年,和大多數(shù)小伙伴們一樣喜歡聽歌游戲,當(dāng)然除此之外還有寫作的興趣,,日子還很長,讓我們一起加油努力叭話 ...
摘要:以上是如果你想精通網(wǎng)絡(luò)爬蟲的學(xué)習(xí)研究路線,按照這些步驟學(xué)習(xí)下去,可以讓你的爬蟲技術(shù)得到非常大的提升。 作者:韋瑋 轉(zhuǎn)載請注明出處 隨著大數(shù)據(jù)時代的到來,人們對數(shù)據(jù)資源的需求越來越多,而爬蟲是一種很好的自動采集數(shù)據(jù)的手段。 那么,如何才能精通Python網(wǎng)絡(luò)爬蟲呢?學(xué)習(xí)Python網(wǎng)絡(luò)爬蟲的路線應(yīng)該如何進行呢?在此為大家具體進行介紹。 1、選擇一款合適的編程語言 事實上,Python、P...
摘要:以下這些項目,你拿來學(xué)習(xí)學(xué)習(xí)練練手。當(dāng)你每個步驟都能做到很優(yōu)秀的時候,你應(yīng)該考慮如何組合這四個步驟,使你的爬蟲達到效率最高,也就是所謂的爬蟲策略問題,爬蟲策略學(xué)習(xí)不是一朝一夕的事情,建議多看看一些比較優(yōu)秀的爬蟲的設(shè)計方案,比如說。 (一)如何學(xué)習(xí)Python 學(xué)習(xí)Python大致可以分為以下幾個階段: 1.剛上手的時候肯定是先過一遍Python最基本的知識,比如說:變量、數(shù)據(jù)結(jié)構(gòu)、語法...
摘要:一時心血來潮,于是當(dāng)時想,如果拿來分析知乎這個網(wǎng)站,會有什么效果呢。知乎并沒有公開,只能采取爬蟲手段。如此,大概率會觸發(fā)知乎反爬蟲系統(tǒng),所以采取以下方法來回避這個問題代理池。但是,很多情況下知乎還是能通過你的請求得到你的真實。。 網(wǎng)站地址books.bigfacewo.com最近工作去了,感覺人也變懶了,一直想寫一些關(guān)于這個網(wǎng)站東西分享出來。慢慢寫吧。前情提要:對于大神來說,這個網(wǎng)站使...
摘要:一時心血來潮,于是當(dāng)時想,如果拿來分析知乎這個網(wǎng)站,會有什么效果呢。知乎并沒有公開,只能采取爬蟲手段。如此,大概率會觸發(fā)知乎反爬蟲系統(tǒng),所以采取以下方法來回避這個問題代理池。但是,很多情況下知乎還是能通過你的請求得到你的真實。。 網(wǎng)站地址books.bigfacewo.com最近工作去了,感覺人也變懶了,一直想寫一些關(guān)于這個網(wǎng)站東西分享出來。慢慢寫吧。前情提要:對于大神來說,這個網(wǎng)站使...
閱讀 1971·2021-09-09 09:33
閱讀 1112·2019-08-30 15:43
閱讀 2657·2019-08-30 13:45
閱讀 3304·2019-08-29 11:00
閱讀 853·2019-08-26 14:01
閱讀 3568·2019-08-26 13:24
閱讀 477·2019-08-26 11:56
閱讀 2686·2019-08-26 10:27