免登录下载微博图片代码研究及优化1.0

1.代码基础:https://github.com/yAnXImIN/weiboPicDownloader.git

2.下载后运行代码初体验

3.找一个微博试试看,看代码文档这里需要微博id,随便找一条微博,找到ouid,这里是火影忍者的微博,id是

 

 

 3.实验一下效果

 

 

 1.最后运行结果为0

 

 

 4.分析一下,可能时间太短,但是重新把时间跨度拉长了几年还是没用。

 

 

 时间已经设置排查到任何时间都会转为1970-01-01,所以我们选的时间都比这个要早,排除了。

 

 

 注释后,不用选择时间重新运行试试,成功。

 

 

 

 

 

 5.继续排雷,找个图片数量多的博客试试, 下载过程中会出现空指针

 

 

 

 

 定位到这里是空的

 

 

加个打印看看,最后没有报错了,看来有可能是

 

 

 

 分析里面的代码,排查一下原因,重新换个id试试。

public static byte[] download(String webUrl, int timeOut) {
        HttpURLConnection connection = null;
        long start = System.currentTimeMillis();
        try {
            URL url = new URL(webUrl);
            connection = (HttpURLConnection) url.openConnection();
            connection.setConnectTimeout(timeOut);
            connection.setReadTimeout(timeOut);
            connection.setRequestProperty("User-Agent", USER_AGENT);
            int len = connection.getContentLength();
        //1.最大图片40M,那些报错的可能就是图片太大。但是第二次执行就没报错排查这里 if (len >= MAX_DOWNLOAD_SIZE) { return null; }
       //2.网络超时了可能。 if (len == -1) { try (InputStream in = connection.getInputStream()) { return IOUtils.toByteArray(connection.getInputStream()); } } else { byte[] data = new byte[len]; byte[] buffer = new byte[4096 * 2]; int count = 0, sum = 0; try (InputStream in = connection.getInputStream()) { while ((count = in.read(buffer)) > 0) { long elapse = System.currentTimeMillis() - start; if (elapse >= timeOut) { data = null; break; } System.arraycopy(buffer, 0, data, sum, count); sum += count; } } return data; } } catch (Exception e) { return null; } finally { if (connection != null) { connection.disconnect(); } } }

出现新的错误

 

 

 

 JsonObject asJsonObject = root.getAsJsonObject("data");
        JsonArray array = asJsonObject.getAsJsonArray("cards");
        for (int i = 0; i < array.size(); i++) {
            JsonObject mblog = array.get(i).getAsJsonObject().getAsJsonObject("mblog");
            if (mblog != null) {
                /*if (WeiboUtils.needFilterDate) {
                    String createAt = mblog.get("created_at").getAsString();
                    String date = WeiboUtils.getDate(createAt);
                    if (date.compareTo(WeiboUtils.startTime) < 0 || date.compareTo(WeiboUtils.endTime) > 0){
                        continue;
                    }
                }*/
                JsonArray pics = mblog.getAsJsonArray("pics");//报错位置代码,看来是对象转数组错误,我们打开链接看看。
                if (pics != null) {
                    for (int j = 0; j < pics.size(); j++) {
                        JsonObject o = pics.get(j).getAsJsonObject();
                        JsonObject large = o.getAsJsonObject("large");
                        if (large != null) {
                            urls.add(large.get("url").getAsString());
                        }
                    }
                }
            }
        }

 

 上图确实是出现了对象,不能直接转数组。代码可以做微调

 JsonArray pics = null;
                try {
                    pics = mblog.getAsJsonArray("pics");
                } catch (Exception e) {
                    pics=new JsonArray();
                    JsonObject temp=mblog.getAsJsonObject("pics");
                    JsonArray finalPics = pics;
                    temp.entrySet().forEach(t->{
                        finalPics.add(t.getValue());
                    });
                    e.printStackTrace();
                }

继续调试上个问题,有时候网络异常会造成这个错误。

 

 我认为这里出现异常可以重新加入队列。

CountDownLatch downLatch = new CountDownLatch(imgUrls.size());
		ExecutorService executor = Executors.newFixedThreadPool(4);
		for(int i=0;i<imgUrls.size();i++){
			executor.submit(new ImageDownloadTask(downLatch, i, imgUrls.get(i)));
		}
		
		downLatch.await();
		System.out.println("图片下载完成, 路径是 " + IMG_LOCATION);
		executor.shutdown(); 

 修改后的代码,下载失败就重新添加到执行数组里重新执行,从总的80%的丢失率直接降低到1%左右,后续丢失了但是循环已经结束也没法重新执行了。

CountDownLatch downLatch = new CountDownLatch(imgUrls.size());
        ExecutorService executor = Executors.newFixedThreadPool(4);
        int j=imgUrls.size();
        for(int i=0;i<imgUrls.size();i++){
            executor.submit(new ImageDownloadTask(downLatch, i, imgUrls.get(i),imgUrls));
            if(i%10==0){
                Thread.sleep(1000);
            }
            System.out.println("总数:"+imgUrls.size());
        }
        
 System.out.println("下载图片: " + ( imageIndex + 1));
            byte[] imgBytes = FileUtils.download(imageUrl, 100_000);
            if(Objects.isNull(imgBytes)){
                System.out.println(imgBytes);
                imageUrls.add(imageUrl);
            }
            FileUtils.byte2File(imgBytes, WeiboDownloader.IMG_LOCATION, imageIndex+1+getSuffix(imageUrl));

这期优化到这里。

新代码:https://github.com/tianxiadatong/wbPicDown

后续构思1.修复大批量下载丢失问题2.加数据库3.图片名称是按数字命名的改成图片地址自带的名称命名。

  

 

posted @ 2022-09-12 17:04  执笔写墨  阅读(252)  评论(0)    收藏  举报