成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

cockroach 爬蟲(chóng):又一個(gè) java 爬蟲(chóng)實(shí)現(xiàn)

liangzai_cool / 2451人閱讀

摘要:爬蟲(chóng)又一個(gè)爬蟲(chóng)實(shí)現(xiàn)原文簡(jiǎn)介小強(qiáng)當(dāng)時(shí)不知道為啥選了這么個(gè)名字,又長(zhǎng)又難記,導(dǎo)致編碼的過(guò)程中因?yàn)閱卧~的拼寫問(wèn)題耽誤了好長(zhǎng)時(shí)間。我是一個(gè)小強(qiáng)爬蟲(chóng)線程數(shù)健壯說(shuō)到健壯,這里主要體現(xiàn)在以下幾個(gè)方面應(yīng)對(duì)封鎖這里我們使用動(dòng)態(tài)代理來(lái)解決這個(gè)問(wèn)題。

cockroach 爬蟲(chóng):又一個(gè) java 爬蟲(chóng)實(shí)現(xiàn)

原文

簡(jiǎn)介

cockroach[小強(qiáng)] 當(dāng)時(shí)不知道為啥選了這么個(gè)名字,又長(zhǎng)又難記,導(dǎo)致編碼的過(guò)程中因?yàn)閱卧~的拼寫問(wèn)題耽誤了好長(zhǎng)時(shí)間。

這個(gè)項(xiàng)目算是我的又一個(gè)坑吧,算起來(lái)挖的坑多了去了,多一個(gè)不多少一個(gè)不少。

一個(gè)小巧、靈活、健壯的爬蟲(chóng)框架,暫且叫做框架吧。

簡(jiǎn)單到什么程度呢,幾句話就可以創(chuàng)建一個(gè)爬蟲(chóng)。

環(huán)境

java8 程序中用到了一些 java8 的新特性

maven


  com.github.zhangyingwei
  cockroach
  1.0.5-Beta

如果哪天我忘了更新文檔了,一定要記住使用最新的版本,最新的版本,新的版本,版本,本。

下面就逐點(diǎn)介紹一下:

小巧

小巧主要體現(xiàn)在兩個(gè)方面

體積小 (打包之后整個(gè) jar 包只有 70k 多一點(diǎn),所以完全擔(dān)得起小巧兩個(gè)字)

開(kāi)發(fā)代碼量小(基于本框架開(kāi)發(fā)一個(gè)爬蟲(chóng)需要的工作量可以說(shuō)是非常小。這個(gè)在下邊的文檔中會(huì)有體現(xiàn))

實(shí)例

在項(xiàng)目中新建一個(gè)測(cè)試類 App.java 并新建 main 方法。

public static void main(String[] args){
    CockroachConfig config = new CockroachConfig()
                    .setAppName("我是一個(gè)小強(qiáng)")
                    .setThread(2); //爬蟲(chóng)線程數(shù)
    CockroachContext context = new CockroachContext(config);
    TaskQueue queue = TaskQueue.of();
    context.start(queue);
    
    // 以上就是一個(gè)完整的爬蟲(chóng),下邊的代碼相當(dāng)于一個(gè)生產(chǎn)者,往隊(duì)列里邊寫任務(wù),一旦寫入任務(wù),爬蟲(chóng)就會(huì)對(duì)任務(wù)進(jìn)行爬取
    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 客戶端(可選,默認(rèn)使用 okhttp3)

可以自定義結(jié)果的處理 (可選,默認(rèn)使用打印處理器)

自定義 http 客戶端

首先我們嘗試一下自定義客戶端

public class SelfHttpClient implements HttpClient {
       public HttpClient setProxy(HttpProxy proxy){
            //設(shè)置代理實(shí)現(xiàn)方法
       }
       public TaskResponse doGet(Task task) throws Exception{
            // get 請(qǐng)求實(shí)現(xiàn)方法
       }
   
       public HttpClient proxy(){
            // 應(yīng)用代理到 http 客戶端 方法
       }
   
       public TaskResponse doPost(Task task) throws Exception{
            // post 請(qǐng)求實(shí)現(xiàn)方法
       }
   
       public HttpClient setCookie(String cookie){
            // 設(shè)置 cookie 實(shí)現(xiàn)方法
       }
   
       public HttpClient setHttpHeader(Map httpHeader){
            // 設(shè)置 header 實(shí)現(xiàn)方法
       }
}

應(yīng)用自定義 http 客戶端到爬蟲(chóng)

CockroachConfig config = new CockroachConfig()
    .setAppName("我是一個(gè)小強(qiáng)")
    .setThread(2) //爬蟲(chóng)線程數(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ǎn)單的將結(jié)果打印了出來(lái),在實(shí)際應(yīng)用中,我們可以保存到數(shù)據(jù)庫(kù)或者保存到文件中等等。值得一說(shuō)的是,如果結(jié)果是 html 網(wǎng)頁(yè)文本的話,我們還提供了 select("css選擇器") 來(lái)對(duì)結(jié)果文本進(jìn)行處理。

應(yīng)用自定義 store 客戶端到爬蟲(chóng)

CockroachConfig config = new CockroachConfig()
    .setAppName("我是一個(gè)小強(qiáng)")
    .setThread(2) //爬蟲(chóng)線程數(shù)
    .setHttpClient(SelfHttpClient.class)
    .setStore(SelfStore.class);
自定義錯(cuò)誤處理類

當(dāng) http 請(qǐng)求網(wǎng)頁(yè)出現(xiàn)錯(cuò)誤的時(shí)候會(huì)統(tǒng)一定位到錯(cuò)誤處理類,如果沒(méi)有自定義錯(cuò)誤處理類,系統(tǒng)會(huì)默認(rèn)使用 DefaultTaskErrorHandler ,此處理類會(huì)吧錯(cuò)誤信息打印出來(lái)。具體實(shí)現(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);
    }
}

如果需要自定義錯(cuò)誤處理類,可以仿照以上代碼,實(shí)現(xiàn) ITaskErrorHandler 接口,在 error 方法中實(shí)現(xiàn)自己的處理邏輯。

在自定義錯(cuò)誤處理類之后,我們需要把自定義類應(yīng)用到爬蟲(chóng)。

CockroachConfig config = new CockroachConfig()
    .setAppName("我是一個(gè)小強(qiáng)")
    .setThread(2) //爬蟲(chóng)線程數(shù)
    .setHttpClient(SelfHttpClient.class)
    .setStore(SelfStore.class)
    .setTaskErrorHandler(SelfTaskErrorHandler.class);
健壯

說(shuō)到健壯,這里主要體現(xiàn)在以下幾個(gè)方面:

應(yīng)對(duì)IP封鎖

這里我們使用動(dòng)態(tài)代理來(lái)解決這個(gè)問(wèn)題。

動(dòng)態(tài)代理的使用
CockroachConfig config = new CockroachConfig()
    .setAppName("我是一個(gè)小強(qiáng)")
    .setThread(2) //爬蟲(chóng)線程數(shù)
    .setHttpClient(SelfHttpClient.class)
    .setProxys("100.100.100.100:8888,101.101.101.101:8888")

如上所示,我們可以設(shè)置若干個(gè)代理 ip,最終將所有代理 ip 生成一個(gè)代理池,在爬蟲(chóng)請(qǐng)求之前,我們會(huì)從代理池中隨機(jī)抽取一個(gè) ip 做代理。

應(yīng)對(duì) http 請(qǐng)求中的 user-agent 問(wèn)題

程序中實(shí)現(xiàn)了一個(gè) user-agent 池,每次請(qǐng)求都會(huì)隨機(jī)取出一個(gè) user-agent 使用,目前在程序中集成了 17 種 user-agent,后續(xù)會(huì)考慮把這塊開(kāi)放出來(lái)到配置中,自定義配置(有沒(méi)有意義呢?)。

程序中的異常處理問(wèn)題

目前在異常處理這塊,本身也不是非常擅長(zhǎng),已經(jīng)盡力把異??刂圃谝粋€(gè)可控的范圍內(nèi),程序中定義了很多自定義異常,這里沒(méi)有什么發(fā)言權(quán),就不細(xì)說(shuō)了,各位要是有意見(jiàn)建議,歡迎拍磚。

所謂深度爬取

程序中并沒(méi)有現(xiàn)成的深度爬取實(shí)現(xiàn),是因?yàn)橐话闱闆r下我并不覺(jué)得深度爬取有什么卵用,但是也不是沒(méi)有為深度爬取留出來(lái)一席之地。我們可以自己提取出頁(yè)面中的鏈接并加入到任務(wù)隊(duì)列中。以達(dá)到深度爬取的效果。

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();
        }
    }
}
注解支持

最近忙里偷閑增加了注解支持,那么在使用注解之后,一個(gè)爬蟲(chóng)是什么樣的呢?

@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);
    }
}

如上就是基本上所有注解的演示,那么拋開(kāi)演示的部分,如果真的只是做一個(gè)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);
    }
}

沒(méi)錯(cuò),就是這么簡(jiǎn)單。這個(gè)爬蟲(chóng)就是爬取 http://blog.zhangyingwei.com 這個(gè)頁(yè)面的內(nèi)容并將結(jié)果打印出來(lái)。
在爬蟲(chóng)結(jié)果處理這個(gè)問(wèn)題上,程序中默認(rèn)使用 PringStore 這個(gè)類將所有結(jié)果打印出來(lái)。

動(dòng)態(tài) header 支持

最近做了一個(gè)工作職位的爬蟲(chóng),在爬拉鉤的時(shí)候遇到一個(gè)問(wèn)題。需要登錄才能爬取,這個(gè)當(dāng)然配置 cookie 就能解決,但是拉鉤的 cookie 里邊做了防爬蟲(chóng)驗(yàn)證。cookie 里邊有一個(gè)時(shí)間需要?jiǎng)討B(tài)變化。所以就產(chǎn)生了這個(gè)功能。

這個(gè)功能使用起來(lái)如下:

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 請(qǐng)求之前,程序都會(huì)調(diào)用 Generator 的 get 方法。獲取到本次的 cookie 值,并附加到 http 請(qǐng)求頭中。

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 對(duì)象,這里是為了在爬蟲(chóng)應(yīng)對(duì)不同的地址的時(shí)候使用不同的 cookie/header 。

算了還是舉個(gè)栗子吧:

/**
 * 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,到此為止,就啰嗦這么多了。

最后,各位大大如果覺(jué)得不討厭的話,來(lái)個(gè) start 唄。

https://github.com/zhangyingwei/cockroach

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/70865.html

相關(guān)文章

  • 【微信小程序爬蟲(chóng)】表情包小程序圖文視頻教學(xué),從零寫起,保姆教程?。?!

    摘要:文章目錄前言爬取分析視頻教學(xué)成果展示福利入門到就業(yè)學(xué)習(xí)路線規(guī)劃小白快速入門爬蟲(chóng)路線前言皮皮蝦一個(gè)沙雕而又有趣的憨憨少年,和大多數(shù)小伙伴們一樣喜歡聽(tīng)歌游戲,當(dāng)然除此之外還有寫作的興趣,,日子還很長(zhǎng),讓我們一起加油努力叭話 ...

    coordinate35 評(píng)論0 收藏0
  • 精通Python網(wǎng)絡(luò)爬蟲(chóng)(0):網(wǎng)絡(luò)爬蟲(chóng)學(xué)習(xí)路線

    摘要:以上是如果你想精通網(wǎng)絡(luò)爬蟲(chóng)的學(xué)習(xí)研究路線,按照這些步驟學(xué)習(xí)下去,可以讓你的爬蟲(chóng)技術(shù)得到非常大的提升。 作者:韋瑋 轉(zhuǎn)載請(qǐng)注明出處 隨著大數(shù)據(jù)時(shí)代的到來(lái),人們對(duì)數(shù)據(jù)資源的需求越來(lái)越多,而爬蟲(chóng)是一種很好的自動(dòng)采集數(shù)據(jù)的手段。 那么,如何才能精通Python網(wǎng)絡(luò)爬蟲(chóng)呢?學(xué)習(xí)Python網(wǎng)絡(luò)爬蟲(chóng)的路線應(yīng)該如何進(jìn)行呢?在此為大家具體進(jìn)行介紹。 1、選擇一款合適的編程語(yǔ)言 事實(shí)上,Python、P...

    spacewander 評(píng)論0 收藏0
  • Python爬蟲(chóng)學(xué)習(xí)路線

    摘要:以下這些項(xiàng)目,你拿來(lái)學(xué)習(xí)學(xué)習(xí)練練手。當(dāng)你每個(gè)步驟都能做到很優(yōu)秀的時(shí)候,你應(yīng)該考慮如何組合這四個(gè)步驟,使你的爬蟲(chóng)達(dá)到效率最高,也就是所謂的爬蟲(chóng)策略問(wèn)題,爬蟲(chóng)策略學(xué)習(xí)不是一朝一夕的事情,建議多看看一些比較優(yōu)秀的爬蟲(chóng)的設(shè)計(jì)方案,比如說(shuō)。 (一)如何學(xué)習(xí)Python 學(xué)習(xí)Python大致可以分為以下幾個(gè)階段: 1.剛上手的時(shí)候肯定是先過(guò)一遍Python最基本的知識(shí),比如說(shuō):變量、數(shù)據(jù)結(jié)構(gòu)、語(yǔ)法...

    liaoyg8023 評(píng)論0 收藏0
  • 知乎書(shū)籍排行網(wǎng)站——建站始末

    摘要:一時(shí)心血來(lái)潮,于是當(dāng)時(shí)想,如果拿來(lái)分析知乎這個(gè)網(wǎng)站,會(huì)有什么效果呢。知乎并沒(méi)有公開(kāi),只能采取爬蟲(chóng)手段。如此,大概率會(huì)觸發(fā)知乎反爬蟲(chóng)系統(tǒng),所以采取以下方法來(lái)回避這個(gè)問(wèn)題代理池。但是,很多情況下知乎還是能通過(guò)你的請(qǐng)求得到你的真實(shí)。。 網(wǎng)站地址books.bigfacewo.com最近工作去了,感覺(jué)人也變懶了,一直想寫一些關(guān)于這個(gè)網(wǎng)站東西分享出來(lái)。慢慢寫吧。前情提要:對(duì)于大神來(lái)說(shuō),這個(gè)網(wǎng)站使...

    Tony 評(píng)論0 收藏0
  • 知乎書(shū)籍排行網(wǎng)站——建站始末

    摘要:一時(shí)心血來(lái)潮,于是當(dāng)時(shí)想,如果拿來(lái)分析知乎這個(gè)網(wǎng)站,會(huì)有什么效果呢。知乎并沒(méi)有公開(kāi),只能采取爬蟲(chóng)手段。如此,大概率會(huì)觸發(fā)知乎反爬蟲(chóng)系統(tǒng),所以采取以下方法來(lái)回避這個(gè)問(wèn)題代理池。但是,很多情況下知乎還是能通過(guò)你的請(qǐng)求得到你的真實(shí)。。 網(wǎng)站地址books.bigfacewo.com最近工作去了,感覺(jué)人也變懶了,一直想寫一些關(guān)于這個(gè)網(wǎng)站東西分享出來(lái)。慢慢寫吧。前情提要:對(duì)于大神來(lái)說(shuō),這個(gè)網(wǎng)站使...

    stormzhang 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<