VS中的Processor合并了页面下载逻辑和页面解析逻辑,在VS理念中,一次资源的获取可以涉及多次网络交互,所以VS的Processor确切的命名是: SeedProcessor,其接口定义如下:

public interface SeedProcessor {
    void process(Seed seed, CrawlerSession crawlerSession, CrawlResult crawlResult);
}

SeedProcessor包含三个参数,分别是seed代表种子;crawlerSession代表用户的会话,crawlResult代表抓取结果。

seed

通俗来说就是这次处理的任务信息,一般来说就是链接信息(URL)。但是对于VS来说,seed可以不是URL,它可以是一个关键字,一个资源ID,一个页码等等。对于垂直爬虫来说,不能限定抓取的输入就是URL的。另一方面,seed包含data字段,类型是String。原因是我觉得seed是需要可序列化的,只要是可以序列化的东西都可以用字符串表示。像webMagic这种容易引起理解误差,同时也容易引发序列化的bug。个人觉得封装成requestBody是没有必要的。

seed有如下功能:

  1. data:存储种子原始信息,一般是URL文本
  2. retry:记录当前重试次数
  3. status:当前种子状态,包括初始化、成功、失败、重试、运行中
  4. maxRetry:当前种子最大重试次数,你没有看错,VS对于种子重试次数的设置,可以精确到每个种子的粒度
  5. ignore:当在processor的时候,如果发现种子是不合法的,则可以置次标志位。这样VS将不会对这个种子执行重试操作
  6. activeTimeStamp:当前种子生效时间,可以设置当前种子在那个时间点进行抓取,如设定在三天后,那么三天后才会对这个种子进行调度。关于延时种子的实现原理,请关注seedManager相关文档
  7. segmentKey:分段标识VS内部使用,非常不建议用户端操作这个字段的值
  8. ext:扩展信息,可由用户自行扩展,是一个hashMap,key-value均为String

crawlerSession

crawlerSession是网络层包装,就代表一个浏览器对象,他是可复用的,由VS框架所管理,属于爬虫框架的资源。一般来说,crawlerSession的个数是有限制的,特别是需要登录的场景,那么有多少个账号最多能够存在多少个crawlerSession。对于crawlerSession,你可以操作的内容如下:

  1. cookieStore: cookie数据,是httpclient对应的cookieStore,如果你想操作cookie,不需要在seed里面放ext信息,直接操作cookieStore即可。
  2. crawlerHttpClient:这是一个httpclient对象,属于dungproxy的知识,他属于closeableHttpClient,所以可以当做普通的httpClient对象使用(这是完全兼容的)。同时为了方便大家使用,她有封装了多个方便的方法。具体文档crawlerHttpClient 相信你会对她爱不释手的。另外,crawlerHttpClient内部的cookieStore和第一条提到的cookieStore是同一个
  3. ipPool:代理池对象,代理池对象是一个抽象的设计,目前默认实现是路由至dungproxy,因为dungproxy代理池封装很强大(dungpoxy-client的代码量都已经接近VS-core了,里面存在的算法控制也是很牛逼的)。当然,你完全可以替换掉它
  4. proxyStrategy:代理策略,代理策略是指你想使用代理的方式,目前包括每次都换IP、每次processor处理的时候更换一次IP、每个用户登录的时候更换一次IP、不代理、自定义代理方式。当然默认值是不代理。对于自定义代理方式,你只需要实现proxyPlanner接口即可,个人觉得这种场景不多,但是还是提供支持
  5. proxyPlanner:代理决定器,其实就是代理策略的具体实现Proxy,他的签名如下
    public interface ProxyPlanner {
       /**
        * 自定义代理规则,如果觉得默认的三种策略(每次请求换代理,每个session换代理,每个用户切换代理)不够使用,可以自定义代理策略
        * 
        * @param host 请求目标主机
        * @param request 请求体
        * @param context 请求的context
        * @param ipPool 代理池对象,可以获取一个IP
        * @param crawlerSession vsCrawler的session,里面封装了单个用户一次回话的所有信息
        * @return 代理对象
        */
       Proxy determineProxy(HttpHost host, HttpRequest request, HttpContext context, IPPool ipPool,
                            CrawlerSession crawlerSession);
    }
    

当然crawlerSession的用法并不多,你一般会这么使用:

使用GET方法请求一个网页

String hrml = crawlerSession.getCrawlerHttpClient().get(url.toString())

使用post方法请求一个网页

String hrml = crawlerSession.getCrawlerHttpClient().post(url.toString(), Lists.newArrayList(NameValuePairBuilder
                .create()
                .addParam("key", "value1")
                .addParam("key2", "value2")
                .addParam("key3", "value3")
                .build()));

提交一个JSON数据:

 Map<String,String> jsonData = Maps.newHashMap();
        jsonData.put("key","value");
        jsonData.put("key2","value2");
        String html =  crawlerSession.getCrawlerHttpClient().postJSON(url.toString(),jsonData);

下载一张图片

        byte[] bytes = crawlerSession.getCrawlerHttpClient().getEntity("http://mtl.ttsqgs.com/uploadfile/2015/0708/20150708092409324.jpg");
        Files.write(bytes, PathResolver.commonDownloadPath("~/Desktop/beauty","http://mtl.ttsqgs.com/uploadfile/2015/0708/20150708092409324.jpg"));

或着普通的httpclient的用法,这种方式用起来麻烦一些,但是post,get,head,option你想怎么玩儿都行

        HttpGet httpGet = new HttpGet(url);
        RequestConfig.Builder builder = RequestConfig.custom().setSocketTimeout(ProxyConstant.SOCKET_TIMEOUT)
                .setConnectTimeout(ProxyConstant.CONNECT_TIMEOUT)
                .setConnectionRequestTimeout(ProxyConstant.REQUEST_TIMEOUT).setRedirectsEnabled(true)
                .setCircularRedirectsAllowed(true);
        httpGet.setConfig(builder.build());
        CloseableHttpResponse closeableHttpResponse = crawlerSession.getCrawlerHttpClient().execute(httpGet);
        int statusCode = closeableHttpResponse.getStatusLine().getStatusCode();
        if(statusCode!=200){
            System.out.println("not 200");
        }
        String data = EntityUtils.toString(closeableHttpResponse.getEntity());

crawResult

这个很简单,就是用来存放抓取结果的,包括抓取结果和新种子两个数据。

results matching ""

    No results matching ""