问题:从指定网址上下载图片到本机。
要求:
- 通过解析页面,分析出指定图片,并且下载。注意:不是指定图片地址。
图片对应的网址: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);
“我将永远忠于自己,披星戴月奔向理想和你”