栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 移动开发 > Android

基于RxJava2实现的简单图片爬虫的方法

Android 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

基于RxJava2实现的简单图片爬虫的方法

今年十月份以来,跟朋友尝试导入一些图片到tensorflow来生成模型,这就需要大量的图片。刚开始我只写了一个简单的HttpClient程序来抓取图片,后来为了通用性索性写一个简单的图片爬虫程序。它可以用于抓取单张图片、多张图片、某个网页下的所有图片、多个网页下的所有图片。

github地址:https://github.com/fengzhizi715/PicCrawler

这个爬虫使用了HttpClient、RxJava2以及Java 8的一些特性。它支持一些简单的定制,比如定制User-Agent、Referer、cookies等。

一.下载安装:

对于Java项目如果使用gradle构建,由于默认不是使用jcenter,需要在相应module的build.gradle中配置

repositories {
  mavenCentral()
  jcenter()
}

Gradle:

compile 'com.cv4j.piccrawler:crawler:0.2.1'

Maven:


 com.cv4j.piccrawler
 crawler
 0.2.1
 pom

二.使用方法:

2.1 下载单张图片

1、普通方式

    String url = "..."; // 图片的地址
    CrawlerClient.get()
 .timeOut(6000)
 .fileStrategy(new FileStrategy() {

   @Override
   public String filePath() {
     return "temp";
   }

   @Override
   public String picFormat() {
     return "png";
   }

   @Override
   public FileGenType genType() {

     return FileGenType.AUTO_INCREMENT;
   }
 })
 .repeat(200) // 重复200次
 .build()
 .downloadPic(url);

在这里,timeOut()表示网络请求的超时时间。fileStrategy()表示存放的目录、文件使用的格式、生成的文件时使用何种策略。repeat()表示对该图片请求重复的次数。

PicCrawler支持多种文件的生成策略,比如随机生成文件名、从1开始自增长地生成文件名、生成指定的文件名等等。

下图显示了使用该程序对某验证码的图片下载200次。


2、使用RxJava的方式下载

    String url = "..."; // 图片的地址
    CrawlerClient.get()
 .timeOut(6000)
 .fileStrategy(new FileStrategy() {

   @Override
   public String filePath() {
     return "temp";
   }

   @Override
   public String picFormat() {
     return "png";
   }

   @Override
   public FileGenType genType() {

     return FileGenType.AUTO_INCREMENT;
   }
 })
 .repeat(200)
 .build()
 .downloadPicUseRx(url);

3、使用RxJava,下载之后的图片还能做后续的处理

    String url = "..."; // 图片的地址
    CrawlerClient.get()
 .timeOut(6000)
 .fileStrategy(new FileStrategy() {

   @Override
   public String filePath() {
     return "temp";
   }

   @Override
   public String picFormat() {
     return "png";
   }

   @Override
   public FileGenType genType() {

     return FileGenType.AUTO_INCREMENT;
   }
 })
 .repeat(200)
 .build()
 .downloadPicToFlowable(url)
 .subscribe(new Consumer() {
   @Override
   public void accept(File file) throws Exception {
     // do something
   }
 });

在Consumer中,可以对文件做一些后续的处理。

2.2 下载多张图片

    List urls = ...; // 多张图片地址的集合
    CrawlerClient.get()
 .timeOut(6000)
 .fileStrategy(new FileStrategy() {

   @Override
   public String filePath() {
     return "temp";
   }

   @Override
   public String picFormat() {
     return "png";
   }

   @Override
   public FileGenType genType() {

     return FileGenType.AUTO_INCREMENT;
   }
 })
 .build()
 .downloadPics(urls);

2.3 下载某个网页的全部图片

    String url = "http://www.jianshu.com/u/4f2c483c12d8"; // 针对某一网址
    CrawlerClient.get()
 .timeOut(6000)
 .fileStrategy(new FileStrategy() {

   @Override
   public String filePath() {
     return "temp";
   }

   @Override
   public String picFormat() {
     return "png";
   }

   @Override
   public FileGenType genType() {

     return FileGenType.AUTO_INCREMENT;
   }
 })
 .build()
 .downloadWebPageImages(url);

使用上面的程序,对我简书主页上的图片进行抓取。


2.4 下载多个网页的全部图片

 

    List urls = new ArrayList<>(); // 多个网页的集合
    urls.add("http://www.jianshu.com/u/4f2c483c12d8");
    urls.add("https://toutiao.io/");
    CrawlerClient.get()
 .timeOut(6000)
 .fileStrategy(new FileStrategy() {
   @Override
   public String filePath() {
     return "temp";
   }

   @Override
   public String picFormat() {
     return "png";
   }

   @Override
   public FileGenType genType() {

     return FileGenType.AUTO_INCREMENT;
   }
 })
 .build()
 .downloadWebPageImages(urls);

下载个人简书主页上的图以及开发者头条的图片。


三. 部分源码解析

3.1 下载某个网页的全部图片

downloadWebPageImages()方法表示下载某个url的全部图片。

  
  public void downloadWebPageImages(String url) {
    Flowable.just(url)
 .map(s->httpManager.createHttpWithGet(s))
 .map(response->parseHtmlToImages(response))
 .subscribe(urls -> downloadPics(urls),
     throwable-> System.out.println(throwable.getMessage()));
  }

downloadWebPageImages()分成三步:创建网络请求、解析出当前页面中包含的图片路径、下载这些图片。

第一步,创建网络请求使用了HttpClient。

  public CloseableHttpResponse createHttpWithGet(String url) {
    // 获取客户端连接对象
    CloseableHttpClient httpClient = getHttpClient();
    // 创建Get请求对象
    HttpGet httpGet = new HttpGet(url);
    if (Preconditions.isNotBlank(httpParam)) {
      Map header = httpParam.getHeader();
      if (Preconditions.isNotBlank(header)) {
 for (String key : header.keySet()) {
   httpGet.setHeader(key,header.get(key));
 }
      }
    }
    CloseableHttpResponse response = null;
    // 执行请求
    try {
      response = httpClient.execute(httpGet);
    } catch (IOException e) {
      e.printStackTrace();
    }
    return response;
  }

第二步,将返回的response转换成String类型,使用jsoup将带有图片的链接全部过滤出来。

jsoup 是一款Java 的HTML解析器,可直接解析某个URL地址、HTML文本内容。它提供了一套非常省力的API,可通过DOM,CSS以及类似于jQuery的操作方法来取出和操作数据。

private List parseHtmlToImages(CloseableHttpResponse response) {
    // 获取响应实体
    HttpEntity entity = response.getEntity();
    InputStream is = null;
    String html = null;
    try {
      is = entity.getContent();
      html = IOUtils.inputStream2String(is);
    } catch (IOException e) {
      e.printStackTrace();
    }
    document doc = Jsoup.parse(html);
    Elements media = doc.select("[src]");
    List urls = new ArrayList<>();
    if (Preconditions.isNotBlank(media)) {
      for (Element src : media) {
 if (src.tagName().equals("img")) {
   if (Preconditions.isNotBlank(src.attr("abs:src"))) { // 图片的绝对路径不为空
     String picUrl = src.attr("abs:src");
     log.info(picUrl);
     urls.add(picUrl);
   } else if (Preconditions.isNotBlank(src.attr("src"))){ // 图片的相对路径不为空
     String picUrl = src.attr("src").replace("//","");
     picUrl = "http://"+Utils.tryToEscapeUrl(picUrl);
     log.info(picUrl);
     urls.add(picUrl);
   }
 }
      }
    }

    if (response != null) {
      try {
 EntityUtils.consume(response.getEntity());
 response.close();
      } catch (IOException e) {
 System.err.println("释放链接错误");
 e.printStackTrace();
      }
    }
    return urls;
  }

第三步,下载这些图片使用了Java 8的CompletableFuture。CompletableFuture是Java 8新增的用于异步处理的类,而且CompletableFuture的性能也好于传统的Future。

  
  public void downloadPics(List urls) {
    if (Preconditions.isNotBlank(urls)) {
      urls.stream().parallel().forEach(url->{
 try {
   CompletableFuture.runAsync(() -> downloadPic(url)).get();
 } catch (InterruptedException e) {
   e.printStackTrace();
 } catch (ExecutionException e) {
   e.printStackTrace();
 }
      });
    }
  }

3.2 下载多个网页的全部图片

downloadWebPageImages()方法还支持传List集合,表示多个网页的地址。

  
  public void downloadWebPageImages(List urls) {
    if (Preconditions.isNotBlank(urls)) {
      Flowable.fromIterable(urls)
   .parallel()
   .map(url->httpManager.createHttpWithGet(url))
   .map(response->parseHtmlToImages(response))
   .sequential()
   .subscribe(list -> downloadPics(list),
throwable-> System.out.println(throwable.getMessage()));
    }
  }

在这里其实用到了ParallelFlowable,因为parallel()可以把Flowable转成ParallelFlowable。

总结

PicCrawler 是一个简单的图片爬虫,目前基本可以满足我的需求。未来要是有新的需求,我会不断添加功能。

在做PicCrawler时,其实还做了一个ProxyPool用于获取可用代理池的库,它也是基于RxJava2实现的。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持考高分网。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/156488.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号