美文网首页小菜鸟
根据URL解析网页并保存相应文件

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

作者: 我是一颗小虎牙_ | 来源:发表于2020-10-15 18:39 被阅读0次
    image

    前言

    <font color=#999AAA >根据URL解析HTML获取文件URL并下载存储</font>

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

    正文

    一、URL内容

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

    image

    事实上他这个标签实在是不规律。只有后面的文件名使用<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服务器的,后来需求改了。这是第一次在项目中使用网页解析,博主会在代码中加很多注释。这里记录下,可作为参考。

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

    相关文章

      网友评论

        本文标题:根据URL解析网页并保存相应文件

        本文链接:https://www.haomeiwen.com/subject/nnpopktx.html