根据URL解析网页并保存相应文件

前言

根据URL解析HTML获取文件URL并下载存储

最近公司接入了一个平台的数据,给了一个连接,存放每天定时推的文件列表。我这里需要做的就是我要把这些文件下载下来,保存到服务器上,其他人那它去用。

正文

一、URL内容

提供的URL使用用户名和密码登录进去长这个样子。这个是<body></body>部分,我主要处理这个部分。

事实上他这个标签实在是不规律。只有后面的文件名使用<a></a>包括。所以只能对这个做文章。

二、需求

每次定时访问这个URL,需要下载自己服务器上的存放位置没有的最新文件,那么需要一个记录值来记录最后下载的一个位置。

当是首次下载,那么没有这个记录值的时候,我只需要下载最新文件中后缀是“f”的压缩包,然后记录这个值。

当是后续下载,需要根据记录值下载它后面的所有文件,然后记录这个值。

二、使用步骤

1.引入库

URL访问和解析使用dom4j的相关东西。

<dependency>
	<groupId>dom4j</groupId>
	<artifactId>dom4j</artifactId>
	<version>1.6.1</version>
</dependency>
<dependency>
	<groupId>jaxen</groupId>
	<artifactId>jaxen</artifactId>
	<version>1.1.6</version>
</dependency>
<dependency>
	<groupId>com.jcraft</groupId>
	<artifactId>jsch</artifactId>
	<version>0.1.49</version>
</dependency>

2.贴代码(长代码警告)

public class FileUtils {

    private static final Logger logger = LoggerFactory.getLogger(DowJonesFileUtils.class);

    private static InputStream inputStream;
    private static BufferedInputStream bi;
    private static HttpURLConnection conn;
    private static URL httpUrl;
    private static OutputStream outputStream;
    private static BufferedOutputStream bo;

    //需要登录的网站
    private static String baseURL = "https://*******.com";
    //记录值文件
    private static String recordFile = "record.txt";
    //文件存放位置
    private static String dirPath = "/data/******";
    
    //定时任务每四个小时执行一次
    @Scheduled(cron = "0 0/4 * * * ?")
    public void operate() throws IOException {
        logger.info("文件下载开始");
        //登录
        FileUtils jones = new FileUtils();
        Connection.Response login = jones.login();
        logger.info("登录成功");

        //解析
        Elements pre_a = jones.parse(login);
        if (pre_a ==null){
            return;
        }
        
        //获取记录的文件信息,确定下载位置
        File file = new File(dirPath+"/"+recordFile);
        //把记录位置以后的文件,作为要下载的文件,集合
        List<String> downURL = jones.getDownURL(pre_a, file);
        if (downURL.size()==0){
            logger.info("没有需要下载的文件");
            logger.info("文件下载结束");
            return;
        }
        logger.info("开始下载,剩余文件数量:"+downURL.size());
        //下载文件
        downFile(downURL);
        logger.info("文件下载结束");
    }

    /**
     * @Description: 登录
     * @param
     * @return org.jsoup.Connection.Response
     * @throws
     * @author Surpass
     * @date 2020/10/15 11:11
     */
    private Connection.Response login(){
        Connection.Response login = null;
        try {
            login = Jsoup.connect("https://***********/XML/1815")
                    .data("Username","****")  //账号
                    .data("Password","********")  //密码
                    .header("Authorization","*******")  //url网站访问权限 请求头里
                    .method(Connection.Method.GET)
                    .execute();
        } catch (IOException e) {
            logger.info("登录异常:",e);
        }
        return login;
    }


    /**
     * @Description: 登录解析html获取文件主体
     * @param login
     * @return org.jsoup.select.Elements
     * @throws
     * @author Surpass
     * @date 2020/10/15 11:09
     */
    private Elements parse(Connection.Response login){
        Document document = null;
        if (login ==null){
            return null;
        }
        try {
            document = login.parse();
        } catch (IOException e) {
            logger.info("解析异常:",e);
        }
        //根据html代码选择获取了所有的链接标签
        Elements pre_a = document.select("pre a");
        return pre_a;
    }

    /**
     * @Description: 根据标签ELe获取需要加载的URL
     * @param pre_a, 标签ELes
     *        baseURL, url前缀
     *        file 记录文件
     * @return java.util.List<java.lang.String>
     * @throws
     * @author Surpass
     * @date 2020/10/14 18:40
     */
    private List<String> getDownURL(Elements pre_a,File file) throws IOException {
        //获取记录文件中的记录时间和全、增量标识
        Double recordData = null;
        char recordType = 0;
        String record = null;
        if (!file.exists()){
            file.createNewFile();
        }else {
            //获取记录文件中的记录值
            Reader reader = new FileReader(file);
            BufferedReader br = new BufferedReader(reader);
            record = br.readLine();
            if (record!=null&&record.trim()!=""){
                String[] split = record.split("_");
                recordData = Double.valueOf(split[0]);
                recordType = split[1].charAt(0);
            }
            if (br!=null){
                br.close();
            }
            if (reader!=null){
                reader.close();
            }
        }

        ArrayList<String> list = new ArrayList<>();
        //标签中的text
        List<String> textList = pre_a.eachText();
        //标签中的属性
        List<String> hrefList = pre_a.eachAttr("href");
        //获取记录值之后的文件URL,存入集合
        for (int i = 0; i < hrefList.size(); i++) {
            String href = hrefList.get(i);
            String downURL = baseURL+href;

            String text = textList.get(i);
            //URL过滤
            if (!text.endsWith(".zip")){
                continue;
            }
            //当有记录值的时候,下载记录值以后的所有文件
            if (StringUtils.isNotBlank(record)){
                String[] textArr = text.split("_");
                Double fileData = Double.valueOf(textArr[4]);
                //当前值和记录值相同
                if (fileData.equals(recordData)){
                    if ( recordType=='f' && textArr[5].charAt(0)=='i' ){
                        list.add(downURL);
                    }
                }
                if (fileData>recordData){
                    list.add(downURL);
                }
            }
            //当没有记录值的时候,只下载最新的全量(当倒数第二个是全量,那么直接跳出循环)
            if (StringUtils.isBlank(record)){
                char flag = textList.get(i).charAt(textList.get(i).length() - 5);
                if (i==hrefList.size()-2&&flag=='f'){
                    list.add(downURL);
                    break;
                }
                if (i==hrefList.size()-1&&flag=='f'){
                    list.add(downURL);
                }
            }
        }
        logger.info("需要下载的URL数量:"+list.size());
        return list;
    }


    /**
     * @Description: 这里是重点了,拿到了需要获取的URL,请求下载并保存
     * @param downURL, 需要下载的文件url
     *        dirPath, 保存文件路径
     *        recordPath 记录文件的位置
     * @return void
     * @throws
     * @author Surpass
     * @date 2020/10/15 11:09
     */
    private void downFile(List<String> downURL) {
        int urlFlag = 0;
        try {
            for (String url : downURL) {
                //文件下载登录
                httpUrl=new URL(url);
                conn=(HttpURLConnection) httpUrl.openConnection();
                conn.setRequestMethod("GET");
                conn.setRequestProperty("Authorization","*******");
                conn.connect();
                logger.info(url+":连接成功");

                //获取输入流
                inputStream = conn.getInputStream();
                bi = new BufferedInputStream(inputStream);
                String fileName = url.substring(url.lastIndexOf("/"));
                //获取输出流
                outputStream = new FileOutputStream(dirPath+fileName);
                bo = new BufferedOutputStream(outputStream);
                byte[] bytes = new byte[1024*10];
                int len = 0;
                while ( (len = bi.read(bytes))!=-1){
                    bo.write(bytes,0,len);
                }
                logger.info("上传URL文件到服务器成功:"+url);

                //记录当前下载位置
                String record = url.substring(69, 83);
                Writer recordWriter = new FileWriter(dirPath+"/"+recordFile);
                BufferedWriter recordBf = new BufferedWriter(recordWriter);
                recordBf.write(record);
                logger.info("上传记录文件record.txt成功");
                //关闭
                recordBf.flush();
                recordBf.close();
                recordWriter.close();

                ++urlFlag;
                logger.info("下载完成,剩余文件数量:"+(downURL.size()-urlFlag));
            }
        }catch (Exception e){
            logger.info("下载失败",e);
        }finally {
            //关闭流
            try {
                if (bo!=null){
                    bo.flush();
                    bo.close();
                }
                if (inputStream!=null){
                    inputStream.close();
                }
                if (bi!=null){
                    bi.close();
                }
                if (outputStream!=null){
                    outputStream.close();
                }

                if (conn!=null){
                    conn.disconnect();
                }
            } catch (IOException e) {
                logger.info("输入流关闭异常",e);
            }
        }
    }
}

3.下载的文件

总结

这一次这个任务结合了网页的解析,用Java下载文件,输入输出流等一些东西,本来文件是存放在sftp服务器的,后来需求改了。这是第一次在项目中使用网页解析,博主会在代码中加很多注释。这里记录下,可作为参考。

当然,代码还存在很多需要完善的地方,还请各位大佬指出不足,后续加倍努力。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值