学以致用 使用OkHttp批量下载小姐姐图片

最近手机上没啥资源了,准备再高一些图片,之前的那个资源网站被我人工扒光了。那个网站还好一点,一页面大概会有5张图片。我可以使用chrome上的插件Fatkun批量下载单页面上的图片。
但这次的网站 www.itmtu.com 一页居然只有1张图片还是全尺寸展示了,妈耶。。。。如果一个套图有100张图片我岂不是要打开一百个网页。。。
而且这个网站屏蔽了右击菜单,下载需要开会员。

这个我能接受?果然F12,还好无异常,有些变态的网站会再在F12的时候清空document,这个时候就只能注入js解锁了。

我随便打开了一个图片网站,F12-> network 可以看到图片相关的请求并拿到图片地址
http://img.itmtu.com/mm/s/slct/x/x.061/0001.jpg

然后我dia
然后我点击下一页查看第二张图片的地址http://img.itmtu.com/mm/s/slct/x/x.061/0002.jpg
我们可以看到图片路径是有规律的,只是文件名就是串四位数字不够用0补齐,我试着改成了http://img.itmtu.com/mm/s/slct/x/x.061/0003.jpg
浏览器地址栏输入,回车,发现能够打开。

这个时候,问题就很简单了,循环替换下图片路径中文件名上的数字批量下载即可。这样就能拿到网站的套图了。

因为我不会python,shell脚本也不太会,所以只能拿起自己的老本行用java写个批量下载的工具类。正好刚刚学习了okhttp,可以练练手。
好,首先我们打开百度,搜索关键词【okhttp 下载文件】,巴拉巴拉猛操作,得到了成品的okhttp下载文件util类。那么我们看看这个工具类里有什么内容。

1.监听器
给的代码里定义了一个监听器接口,主要用于自定义处理一些下载事件,当然你可以不写,硬编码也不会有人打你的啦,反正自己写着玩。

    public interface OnDownloadListener {
        /**
         * 下载成功之后的文件
         */
        void onDownloadSuccess(File file);

        /**
         * 下载进度
         */
        void onDownloading(int progress);

        /**
         * 下载异常信息
         */
        void onDownloadFailed(Exception e);
    }

2.文件下载核心实现方法
代码有点长 说明内容我就直接写代码的注释上了。没写过不知道怎么写,但是看肯定看的懂。

    /**
     * @param url          下载连接
     * @param destFileDir  下载的文件储存目录
     * @param destFileName 下载文件名称
     * @param listener     下载监听
     */
    public void download(final String url, final String destFileDir, final String destFileName, final OnDownloadListener listener) {
        // 构建一个非常基本的request,只有一个url不带任何设置和参数
        Request request = new Request.Builder()
                .url(url)
                .build();

        //异步请求 
        okHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                // 下载失败监听回调
                listener.onDownloadFailed(e);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                InputStream is = null;
                // 2Kb的小缓存
                byte[] buf = new byte[2048];
                int len = 0;
                FileOutputStream fos = null;
                //储存下载文件的目录
                File dir = new File(destFileDir);
                if (!dir.exists()) {
                    dir.mkdirs();
                }
                File file = new File(dir, destFileName);
                try {
                     // 获取响应的字节流 这个时候 请求的数据还没返回接受
                    is = response.body().byteStream();
                    // 获取下下载文件的大小 用于判断下载进度百分比
                    long total = response.body().contentLength();
                     // 创建一个文件输出流用于写文件
                    fos = new FileOutputStream(file);
                    // 文件已写入长度
                    long sum = 0;
                    while ((len = is.read(buf)) != -1) {
                        fos.write(buf, 0, len);
                        sum += len;
                        int progress = (int) (sum * 1.0f / total * 100);
                        //下载中更新进度条
                        listener.onDownloading(progress);
                    }
                    fos.flush();
                    //下载完成
                    listener.onDownloadSuccess(file);
                } catch (Exception e) {
                    listener.onDownloadFailed(e);
                } finally {
                    try {
                        if (is != null) {
                            is.close();
                        }
                        if (fos != null) {
                            fos.close();
                        }
                    } catch (IOException e) {
                    }
                }
            }
        });
    }

3.构建一个 OkHttpClient

这个网站访问的比较慢,所以设置超长的180s超时事件 并使用了一个本地代理加速下载。

OkHttpClient okHttpClient =
      new OkHttpClient.Builder()
             .callTimeout(180, TimeUnit.SECONDS)
             .proxy(new Proxy(Proxy.Type.HTTP,
                     new InetSocketAddress("127.0.0.1", 1081)))
             .build();

4.监听接口实现类
没啥东西,只是打印一些数据

    private static void downFile(String url, String name) {
        DownloadUtil.get().download(url, "E:\\4\\", name + ".jpg",
                new DownloadUtil.OnDownloadListener() {
                    @Override
                    public void onDownloadSuccess(File file) {

                        System.out.println("success");
                    }

                    @Override
                    public void onDownloading(int progress) {
                       // System.out.println(progress + "");
                    }

                    @Override
                    public void onDownloadFailed(Exception e) {
                        //下载异常进行相关提示操作
                        System.err.println(e.getMessage());
                    }
                });

    }

5.主方法
循环体的69表示套图有69张图片,循环拼凑出网站的图片路径并调用下载

    public static void main(String[] args) throws InterruptedException {
        for (int i = 1; i <= 69; i++) {
            String name = "";
            if (i < 10) {
                name = "00" + i;
            } else if (i < 99) {
                name = "0" + i;
            } else {
                name = "" + i;
            }
            downFile("http://img.itmtu.com/mm/s/slct/alpha/alpha.008/0" + name + ".jpg", name);
        }

    }

6.run一下下(声明一下 这些都是正常图片 哪怕发微博也不会屏蔽)

点赞
  1. 头像 emmm说道:

    我有一个不成熟的想法

  2. 头像 kelejichitao说道:
    Google Chrome Windows 10

    哈哈,我之前也遇到这种问题,用idm解决了,支持通配符批量下载

发表评论

电子邮件地址不会被公开。必填项已用 * 标注