博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
基于RxJava2实现的简单图片爬虫
阅读量:5873 次
发布时间:2019-06-19

本文共 9718 字,大约阅读时间需要 32 分钟。

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

github地址:

这个爬虫使用了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次。

下载200张验证码的图片.png

  1. 使用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);复制代码
  1. 使用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);复制代码

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

简书的主页.png

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);复制代码

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

多个网址的图片下载.png

三. 部分源码解析

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

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

/**     * 下载整个网页的全部图片     * @param 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。

/**     * 下载多张图片     * @param urls     */    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集合,表示多个网页的地址。

/**     * 下载多个网页的全部图片     * @param urls     */    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时,其实还做了一个用于获取可用代理池的库,它也是基于RxJava2实现的。

转载地址:http://rphnx.baihongyu.com/

你可能感兴趣的文章
双网卡centos7 iptables防火墙与/etc/rc.d/rc.local开机运行
查看>>
tomcat PermGen space 不足的解决方法
查看>>
STM32系统滴答_及不可不知的延时技巧 - (上)
查看>>
Linux下企业级分区方案
查看>>
CentOS下LAMP一键yum安装脚本
查看>>
拖来拖去今天终于重装系统了
查看>>
NestJS 脑图
查看>>
我的友情链接
查看>>
Html body的滚动条禁止与启用
查看>>
Tengine新增nginx upstream模块的使用
查看>>
多媒体工具Mediainfo
查看>>
1-小程序
查看>>
CentOS图形界面和命令行切换
查看>>
HTML5通信机制与html5地理信息定位(gps)
查看>>
Mind_Manager_2
查看>>
手动升级 Confluence - 规划你的升级
查看>>
汽车常识全面介绍 - 悬挂系统
查看>>
电子政务方向:We7.Cloud政府云门户
查看>>
虚拟机Centos7连接Internet
查看>>
ansible 基本操作(初试)
查看>>