問題:從指定網址上下載圖片到本機。
要求:
- 通過解析頁面,分析出指定圖片,並且下載。注意:不是指定圖片地址。
圖片對應的網址:http://origin.cpc.ncep.noaa.gov/products/people/mchen/CFSv2FCST/monthly/ 要求,下載其中的SST這一列的全部圖片。 - 下載前對圖片是否已經存在要做判斷。
提示:java解析網址用jsoup
1. 提前說明:本文使用maven完成,因為用到了Jsoup,pom文件中肯定要引啦。此外我還引入了log4j、slf4j-log4j12、commons-net。
口說無憑,pom.xml文件如下(dependencies部分)
<dependencies> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.7</version> </dependency> <dependency> <groupId>commons-net</groupId> <artifactId>commons-net</artifactId> <version>3.6</version> </dependency> <dependency> <groupId>org.jsoup</groupId> <artifactId>jsoup</artifactId> <version>1.10.2</version> </dependency> </dependencies>
2. 全部引入后,配置log4j文件,將其放到 \src\main\resources目錄下,取名log4j.properties(沒有引入log4j、slf4j-log4j12的此步忽略)
log4j.properties配置文件如下:
log4j.rootLogger=INFO,Console,File
#定義日志輸出目的地為控制台
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.Target=System.out
#可以靈活地指定日志輸出格式,下面一行是指定具體的格式
log4j.appender.Console.layout = org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=[%d{yyyy-MM-dd HH\:mm} %c] - %m%n
#文件大小到達指定尺寸的時候產生一個新的文件
log4j.appender.File = org.apache.log4j.RollingFileAppender
#指定輸出目錄
log4j.appender.File.File = logs/info.log
#定義文件最大大小
log4j.appender.File.MaxFileSize = 10MB
# 輸出所有日志,如果換成DEBUG表示輸出DEBUG以上級別日志
log4j.appender.File.Threshold = ALL
log4j.appender.File.layout = org.apache.log4j.PatternLayout
log4j.appender.File.layout.ConversionPattern =[%p] [%d{yyyy-MM-dd HH\:mm\:ss}][%c]%m%n
3. 開始擼碼
1 package com.url; 2 3 import org.jsoup.Jsoup; 4 import org.jsoup.nodes.Document; 5 import org.jsoup.nodes.Element; 6 import org.jsoup.select.Elements; 7 import org.slf4j.Logger; 8 import org.slf4j.LoggerFactory; 9 10 import java.io.*; 11 import java.net.HttpURLConnection; 12 import java.net.MalformedURLException; 13 import java.net.URL; 14 import java.net.URLEncoder; 15 16 /** 17 * @author 清風明月 18 * @description 19 * @date 2019/7/14 14:08 20 */ 21 public class ParseUrl { 22 private static final Logger logger = LoggerFactory.getLogger(ParseUrl.class); 23 private static final String HTTP_URL = "https://origin.cpc.ncep.noaa.gov/products/people/mchen/CFSv2FCST/monthly/"; 24 private static final String IMAGE_PATH = "E:\\Projects\\image"; 25 26 public static void main(String[] args) { 27 try { 28 Document document = Jsoup.connect(HTTP_URL).get(); 29 Element table = document.getElementsByTag("table").get(0); 30 Elements trs = table.select("tr"); 31 for (int i = 2; i < trs.size(); i++) { 32 Element td = trs.get(i).select("td").get(1); 33 Elements a = td.select("a[href^=images]"); 34 String image = a.attr("href"); 35 String imgUrl = HTTP_URL + image; 36 downImages(imgUrl); 37 } 38 logger.info("本組圖片已全部保存到" + IMAGE_PATH); 39 } catch (IOException e) { 40 e.printStackTrace(); 41 logger.error("讀取頁面內容失敗"); 42 } 43 } 44 45 /** 46 * @param [imgUrl] 47 * @return void 48 * @author 清風明月 49 * @date 2019/7/16 13:59 50 */ 51 private static void downImages(String imgUrl) { 52 File imgFilePath = new File(IMAGE_PATH); 53 //如果目錄不存在,創建目錄 54 if (!imgFilePath.exists()) { 55 boolean mkdir = imgFilePath.mkdir(); 56 logger.info(mkdir ? "程序已自動創建目錄" : ""); 57 } 58 //拼接image下載地址 59 String beforeUrl = imgUrl.substring(0, imgUrl.lastIndexOf("/") + 1); 60 String imgName = imgUrl.substring(imgUrl.lastIndexOf("/") + 1); 61 String newImgName = imgName; 62 63 try { 64 newImgName = URLEncoder.encode(imgName, "UTF-8"); 65 } catch (UnsupportedEncodingException e) { 66 logger.error("圖片名稱有誤"); 67 e.printStackTrace(); 68 } 69 imgUrl = beforeUrl + newImgName; 70 try { 71 //獲取下載地址 72 URL url = new URL(imgUrl); 73 InputStream in = null; 74 OutputStream out = null; 75 try { 76 //鏈接網絡地址,創建連接對象 77 HttpURLConnection connection = (HttpURLConnection) url.openConnection(); 78 //建立到遠程對象的實際連接 79 connection.connect(); 80 //連接成功 81 if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) { 82 //獲取鏈接的輸入流 83 in = connection.getInputStream(); 84 //創建下載到本地的文件 85 File imgFile = new File(IMAGE_PATH, imgName); 86 if (imgFile.exists()) { 87 logger.info(imgName + " 該圖片已存在"); 88 } else { 89 //寫入文件 90 out = new FileOutputStream(imgFile); 91 byte[] buf = new byte[1024]; 92 int len; 93 while ((len = in.read(buf)) != -1) { 94 out.write(buf, 0, len); 95 } 96 out.flush(); 97 //斷開連接 98 connection.disconnect(); 99 logger.info(imgName + "下載成功"); 100 } 101 } else { 102 logger.warn("連接失敗"); 103 } 104 105 } catch (IOException e) { 106 logger.error("下載圖片失敗"); 107 e.printStackTrace(); 108 } finally { 109 try { 110 if (out != null) { 111 out.close(); 112 } 113 114 if (in != null) { 115 in.close(); 116 } 117 } catch (IOException e) { 118 logger.error("讀寫流關閉出現異常"); 119 e.printStackTrace(); 120 } 121 } 122 } catch (MalformedURLException e) { 123 logger.error("網址格式錯誤"); 124 e.printStackTrace(); 125 } 126 } 127 }
至此,大功告成。
最后給各位提兩點建議(包括我):
- 調用close()方法前,手動加上flush()方法,並且close()方法盡量放在finally中,不要偷懶。否則有可能出現文件(包括圖片、word文檔等)下載完成卻無法打開的情況;
- 如果下載的文件只有1KB,建議查看URL是否正確(例如https://少了s);
“我將永遠忠於自己,披星戴月奔向理想和你”