基於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:
<dependency>
<groupId>com.cv4j.piccrawler</groupId>
<artifactId>crawler</artifactId>
<version>0.2.1</version>
<type>pom</type>
</dependency>
二.使用方法:
2.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次。
- 使用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);
- 使用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<File>() {
@Override
public void accept(File file) throws Exception {
// do something
}
});
在Consumer中,可以對檔案做一些後續的處理。
2.2 下載多張圖片
List<String> 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<String> 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的全部圖片。
/**
* 下載整個網頁的全部圖片
* @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<String,String> 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<String> 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<String> 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<String> 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<String> 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實現的。
相關文章
- go語言實現簡單爬蟲獲取頁面圖片Go爬蟲
- 簡單的爬蟲:爬取網站內容正文與圖片爬蟲網站
- 基於Python的簡單天氣爬蟲程式Python爬蟲
- 基於Python PIL實現簡單圖片格式轉化器Python
- Python 爬蟲零基礎教程(1):爬單個圖片Python爬蟲
- 實現一個簡單的基於 WebAssembly 的圖片處理應用Web
- 使用正則編寫簡單的爬蟲爬取某網站的圖片爬蟲網站
- 用雲函式快速實現圖片爬蟲函式爬蟲
- python爬蟲簡單實現逆向JS解密Python爬蟲JS解密
- 實現簡單的輪播圖(單張圖片、多張圖片)
- java實現一個簡單的爬蟲小程式Java爬蟲
- 使用Python爬蟲實現自動下載圖片Python爬蟲
- 基於 ZooKeeper 實現爬蟲叢集的監控爬蟲
- 最簡單的網路圖片的爬取 --Pyhon網路爬蟲與資訊獲取爬蟲
- 簡單的爬蟲程式爬蟲
- 一個實現批量抓取淘女郎寫真圖片的爬蟲爬蟲
- python 爬蟲 簡單實現百度翻譯Python爬蟲
- Java爬蟲批量爬取圖片Java爬蟲
- 基於React Hook實現圖片的裁剪ReactHook
- Python爬蟲實戰詳解:爬取圖片之家Python爬蟲
- 爬蟲 Scrapy框架 爬取圖蟲圖片並下載爬蟲框架
- 【python--爬蟲】千圖網高清背景圖片爬蟲Python爬蟲
- python如何實現簡單的爬蟲功能?Python學習教程!Python爬蟲
- python爬蟲:爬蟲的簡單介紹及requests模組的簡單使用Python爬蟲
- node:爬蟲爬取網頁圖片爬蟲網頁
- 爬蟲---xpath解析(爬取美女圖片)爬蟲
- python爬蟲---網頁爬蟲,圖片爬蟲,文章爬蟲,Python爬蟲爬取新聞網站新聞Python爬蟲網頁網站
- python簡單爬蟲(二)Python爬蟲
- 誰說爬蟲只能Python?看我用C#快速簡單實現爬蟲開發和演示!爬蟲PythonC#
- Python爬蟲—爬取某網站圖片Python爬蟲網站
- Java培訓教程之使用Jsoup實現簡單的爬蟲技術JavaJS爬蟲
- 如何用Python爬蟲實現百度圖片自動下載?Python爬蟲
- 使用jpeg圖片庫,顯示圖片並簡單實現LCD的觸屏功能
- ReactPHP 爬蟲實戰:下載整個網站的圖片ReactPHP爬蟲網站
- Python爬蟲入門【5】:27270圖片爬取Python爬蟲
- 簡單瞭解python爬蟲Python爬蟲
- 基於java的分散式爬蟲Java分散式爬蟲
- 爬蟲,其實本就是這麼簡單爬蟲
- 《Python開發簡單爬蟲》實踐筆記Python爬蟲筆記