renwuqiangg 发表于 2018-4-25 16:15

【Java】Java批量下载必应壁纸工具

本帖最后由 renwuqiangg 于 2018-4-25 23:07 编辑

我发现这个网站的壁纸还不错 ,这些壁纸都是必应首页的背景,每天只更新一张!https://bing.ioliu.cn/ranking
如果一张一张下载太慢了,遂写了一个批量下载工具,原理也比较简单,适合初学者。输入页码,不一会儿就下载完了。只要明白了其中的原理,下载别的网站的壁纸改改相关代码就行了。
下载完后可以设置win10的背景为幻灯片,并定位到该文件夹。





只有3个类,DownloadThread.java,Msg.java,Test.java。一个jar包 :Jsoup-1.8.2.jar。

package com.ren;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;

public class DownloadThread extends Thread {
      private String filePath = "";
      private String imgUrl = "";
      private Msg msg;
      public DownloadThread(String filePath, String imgUrl,Msg msg) {
                this.filePath = filePath;
                this.imgUrl = imgUrl;
                this.msg = msg;
      }
      @Override
      public void run() {
                msg.addCount();
                downImages(filePath, imgUrl);
      }
      /**
   * 下载图片到指定目录
   *
   * @param filePath 文件路径
   * @param imgUrl   图片URL
   */
      public void downImages(String filePath, String imgUrl) {
      // 若指定文件夹没有,则先创建
      File dir = new File(filePath);
      if (!dir.exists()) {
            dir.mkdirs();
      }
      // 截取图片文件名
      String fileName = imgUrl.substring(imgUrl.lastIndexOf('/') + 1, imgUrl.length());
      String fileName0 = lexicalAnalysis(fileName)+".jpg";
      // 写出的路径
      File file = new File(filePath + File.separator + fileName0);
      if(file.exists()){
                System.out.println("文件已存在["+fileName+"]");
                msg.addRepeat();
                return ;
      }
      try {
            URL url = new URL(imgUrl);
            URLConnection connection = url.openConnection();
            // 设置10秒的相应时间
            connection.setConnectTimeout(10 * 1000);
            InputStream in = connection.getInputStream();
            BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file));
            byte[] buf = new byte;
            int size;
            // 写入到文件
            while (-1 != (size = in.read(buf))) {
                out.write(buf, 0, size);
            }
            out.close();
            in.close();
      } catch (MalformedURLException e) {
                msg.addError();
            e.printStackTrace();
      } catch (IOException e) {
                msg.addError();
            e.printStackTrace();
      }
      msg.addSuccess();
    }
      //原文件名似乎含有特殊字符导致程序出错,简易的词法分析过滤一下
    public static String lexicalAnalysis(String str){
            StringBuffer sb = new StringBuffer();
            int status = 0;
            for (int i = 0; i < str.length(); i++) {
                        char c = str.charAt(i);
                        if((c>='a'&&c<='z')||(c>='A'&&c<='Z')||(c>='0'&&c<='9')){
                              if(status==0){
                                        status=1;
                                        sb.append(c);
                              }else if(status==1){
                                        sb.append(c);
                              }
                        }else{
                              if(status==1){
                                        break;
                              }
                        }
                }
                return sb.toString();
    }

}


Msg.java主要用于记录总共下载了多少,成功了多少等
package com.ren;

public class Msg {
      private int count;
      private int repeat;
      private int success;
      private int error;

      public synchronized void addCount(){
                count++;
      }
      public synchronized void addRepeat(){
                repeat++;
      }
      public synchronized void addSuccess(){
                success++;
      }
      public synchronized void addError(){
                error++;
      }
      @Override
      public String toString() {
                // TODO Auto-generated method stub
                return "总共["+count+"],成功["+success+"],重复["+repeat+"],异常["+error+"]";
      }
}


这里采用线程池,开启10个线程进行下载,但好像网速还是只有100kb/s,可能是服务器的原因吧。
package com.ren;

import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

public class Test {

      public static void main(String[] args) {
                long start = System.currentTimeMillis();
                try {
                        new Test().downloadBing(0,10);
                } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                } catch (ExecutionException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                }
                long end = System.currentTimeMillis();
                System.out.println("耗时:"+((end-start)/1000)+"s");
      }
      /**
         * 必应下载榜
         * @param formpage
         * @param topage
         * @throws IOException
         * @throws ExecutionException
         * @throws InterruptedException
         */
      public void downloadBing(int formpage,int topage) throws IOException, InterruptedException, ExecutionException{
                String downloadUrlPre = "https://bing.ioliu.cn";
                String hostUrlPre = "https://bing.ioliu.cn/ranking?p=";
                String filePath = "D:/renwu/Pictures/壁纸";
                Msg msg = new Msg();
                ExecutorService pool =Executors.newFixedThreadPool(10);
               
                for (int i = formpage; i < topage; i++) {
                        System.out.println("正在下载第["+i+"]页,url:"+hostUrlPre+i);
                        Document doc = Jsoup.connect(hostUrlPre+i).get();
                        Elements divs = doc.select("a.ctrl.download");
                        for (Element element : divs) {
                              String href = element.attr("href");
                              String downloadUrl = downloadUrlPre+href;                              
                              pool.submit(new DownloadThread(filePath, downloadUrl,msg));
                        }
                }
                pool.shutdown();
                while(true){
            if(pool.isTerminated()){
                  System.out.println(msg);
                break;
            }
            Thread.sleep(1000);   
      }
               
      }
}


如何运行:在eclipse新建项目,百度下载Jsoup-1.8.2.jar,加入项目的build path。新建DownloadThread.java,Msg.java,Test.java三个类并将代码复制进去,运行test即可。

FACED 发表于 2018-4-25 16:26

mark!感谢分享

410791007 发表于 2018-4-25 16:35

哎,小白,不懂,{:1_907:}有成品吗?{:1_908:}{:1_908:}{:1_896:}

感觉不到风 发表于 2018-4-25 16:45

mark 一下 test.java 还没有看 回头再看

Titanic 发表于 2018-4-25 16:49

可以的,感谢分享。

laozhangty 发表于 2018-4-25 17:32

原创分享,值得赞扬

羽橙雨 发表于 2018-4-27 11:27

楼主厉害,请问楼主JAVAse是自学的吗,感觉基础很扎实

qiyou 发表于 2018-4-27 18:36

看起来不错拿走了

km852753951 发表于 2018-6-22 10:15

多谢楼主 学习一下

端木匆匆 发表于 2018-11-12 13:34

本帖最后由 端木匆匆 于 2018-11-12 13:46 编辑

依葫芦画瓢做了一个,请问这个错是啥意思?
      javax.net.ssl.SSLException: SSL peer shut down incorrectly
      at sun.security.ssl.InputRecord.readV3Record(Unknown Source)
      at sun.security.ssl.InputRecord.read(Unknown Source)
      at sun.security.ssl.SSLSocketImpl.readRecord(Unknown Source)
      at sun.security.ssl.SSLSocketImpl.readDataRecord(Unknown Source)
      at sun.security.ssl.AppInputStream.read(Unknown Source)
      at java.io.BufferedInputStream.fill(Unknown Source)
      at java.io.BufferedInputStream.read1(Unknown Source)
      at java.io.BufferedInputStream.read(Unknown Source)
      at sun.net.www.http.ChunkedInputStream.fastRead(Unknown Source)
      at sun.net.www.http.ChunkedInputStream.read(Unknown Source)
      at java.io.FilterInputStream.read(Unknown Source)
      at sun.net.www.protocol.http.HttpURLConnection$HttpInputStream.read(Unknown Source)
      at sun.net.www.protocol.http.HttpURLConnection$HttpInputStream.read(Unknown Source)
      at com.ren.DownloadThread.downImages(DownloadThread.java:58)
      at com.ren.DownloadThread.run(DownloadThread.java:24)
      at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
      at java.util.concurrent.FutureTask.run(Unknown Source)
      at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
      at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
      at java.lang.Thread.run(Unknown Source)
页: [1] 2
查看完整版本: 【Java】Java批量下载必应壁纸工具