Java抓取网页图片并保存到本地(HTTPS)


下面仅介绍用添加安全证书的方式,下载HTTPS网页图片到本地

一,下载网页安全证书到本地

以Chrome为例,打开相关网站,在地址栏的锁图标上单击,再单击【连接是安全的】-》【证书有效】-》【详细信息】-》【复制到文件】,将证书以默认格式保存到本地。本文以khl.cer为例。

二,导入证书到本地keystore

Windows10中,按【Win+X】,选择【Windows终端(管理员)】,以管理员运行PowerShell,在窗口中,先切换到JAVA_HOME\jre\bin目录,本文是C:\Java\jdk1.8.0_144\jre\bin

注意:如果路径有空格,请在路径上加上引号

然后执行导入命令:

keytool -import -v -trustcacerts -alias my_cert -file D:\TDDOWNLOAD\khl.cer -storepass changeit -keystore "C:\Java\jdk1.8.0_144\jre\lib\security\cacerts"

如果路径有不同,请做相应更改。整体效果如下图,在问及是否信任此证书时,输入【y】

 三,Java实现代码

注意,请直接参考代码中的startDownload方法即可。本程序是实现将网站上的图片全部抓取下来的(图片地址存储于MySQL数据库中)

package com.clzhang.sample.net;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

public class DownloadImgFromKHL {
    // 数据库配置信息,注意:MySQL8的JDBC URL不同于之前版本
    public static final String MYSQL_JDBC_URL = "jdbc:mysql://localhost:3306/jhl?useUnicode=true&characterEncoding=UTF8&serverTimezone=GMT%2B8&useSSL=false";

    /**
     * 主处理程序
     * 
     * @throws Exception
     */
    public void process() throws Exception {
        // MySQL8开始,用如下类进行处理;数据库的用户名与密码,不要存放到JDBC URL中,而是在获取连接时加入
        Class.forName("com.mysql.cj.jdbc.Driver");
        // 数据库连接句柄
        Connection conn = null;

        String SELECT_SQL = "select id,image1,image2,image3,image4,image5 from lfdata where id>? order by id asc";
        try {
            conn = DriverManager.getConnection(MYSQL_JDBC_URL, "root", "admin");

            PreparedStatement pstmt = conn.prepareStatement(SELECT_SQL);
            pstmt.setInt(1, 44561);
            ResultSet rs = pstmt.executeQuery();
            while (rs.next()) {
                List listImg = new ArrayList();
                String id = rs.getString("id");
                String image1 = rs.getString("image1");
                String image2 = rs.getString("image2");
                String image3 = rs.getString("image3");
                String image4 = rs.getString("image4");
                String image5 = rs.getString("image5");
                if (image1 != null && image1.length() > 0)
                    listImg.add(image1);
                if (image2 != null && image2.length() > 0)
                    listImg.add(image2);
                if (image3 != null && image3.length() > 0)
                    listImg.add(image3);
                if (image4 != null && image4.length() > 0)
                    listImg.add(image4);
                if (image5 != null && image5.length() > 0)
                    listImg.add(image5);

                startDownload(listImg);
                System.out.println(id);
            }
            rs.close();
            pstmt.close();
        } finally {
            // TODO: handle finally clause
            if (conn != null)
                conn.close();
        }
    }

    private void startDownload(List listImg) {
        try {
            for (String strURL : listImg) {
                System.out.println(strURL);
                String imageName = "D:\\TDDOWNLOAD\\uploads\\"
                        + strURL.substring(strURL.lastIndexOf("/") + 1, strURL.length());
                
                URL url = new URL(strURL);
                URLConnection conn = url.openConnection();
                //设置超时间为3秒
                conn.setConnectTimeout(3 * 1000);
                //防止屏蔽程序抓取而返回403错误
                conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
                //输出流
                InputStream str = conn.getInputStream();
                //控制流的大小为1k
                byte[] bs = new byte[1024];
                //读取到的长度
                int len = 0;
                //是否需要创建文件夹
                File file = new File(imageName);
                //实例输出一个对象
                FileOutputStream out = new FileOutputStream(file);
                //循环判断,如果读取的个数b为空了,则is.read()方法返回-1,具体请参考InputStream的read();
                while ((len = str.read(bs)) != -1) {
                    //将对象写入到对应的文件中
                    out.write(bs, 0, len);
                }
                //刷新流
                out.flush();
                //关闭流
                out.close();
                str.close();
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public static void main(String[] args) throws Exception {
        DownloadImgFromKHL ins = new DownloadImgFromKHL();
        ins.process();
    }
}