找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
广告投放联系QQ68610888
查看: 435|回复: 0

Java手写下载某香蕉平台的视频

[复制链接]
发表于 2022-12-5 15:50 | 显示全部楼层 |阅读模式
隔壁论坛也是我发布的,但是非注册用户可能看不到。在恩山再发一贴,如有不符合版规还清管理员移动到对应板块,谢谢。




文中域名均已脱敏,且原域名都失效,不要回复要域名的。楼主也想知道新域名呢

先api抓取数据,抓换成iptv可以播放的看下在线的



  1. public static void main(String[] args) {
  2.        /*String s = "145_/hd_0152,https://aaaaaaaaa.com/video/12/hd_0152/hd_0152.m3u8";
  3.         int a = s.lastIndexOf("/"); //去掉最后一个','号
  4.         String s1 = s.substring(a + 1, s.length());
  5.         String hd = s.substring(a + 1, a + 3);
  6.         System.out.println("" + hd);
  7.         int b = s.lastIndexOf("."); //去掉最后一个','号
  8.         String tvgid = s.substring(a + 1, b);
  9.         int c = s.lastIndexOf("http"); //去掉最后一个','号
  10.         System.out.println(s.substring(c, s.length()));
  11.         String img = ""+s.substring(c, a).replaceAll("video","img")+".jpg";
  12.         String m3 = "#EXTINF:-1 tvg-id="%s" tvg-name="%s" tvg-logo="%s" tvg-language="Chinese" tvg-country="CN" group-title="",%s";
  13.         String m = String.format(m3, tvgid, s1,img, s1);
  14.         System.out.println(m);*/

  15.         String url = "http://aaaaaaalebu.com/video_list.php?id=17&on=20&n=10";
  16.         String jsonStr = http(url);

  17.         json(jsonStr, "04");

  18.         StringBuilder builder = readFileByBytes("C:/upload/aaa/04.txt");
  19.         if (builder != null) {
  20.             try {
  21.                 File file1 = new File("C:\\upload\\aaa\\04m3.txt");
  22.                 BufferedWriter bw = new BufferedWriter(new FileWriter(file1));
  23.                 bw.write(builder.toString());
  24.                 bw.flush();
  25.                 bw.close();
  26.             } catch (Exception e) {
  27.                 e.printStackTrace();
  28.             }
  29.         }

  30.     }

  31.                 //组合出下面的 IPTV格式
  32.                 #EXTM3U
  33. #EXTINF:-1 tvg-id="jr_0068" tvg-name="姐我" tvg-logo="https://aaaaaaaaaaa.com/img/17/jr_0068.jpg" tvg-language="Chinese" tvg-country="CN" group-title="",姐我
复制代码


在线看不如存起来,想办法给下载下来,下载了大概500G吧。先写个下载工具类






  1.         /**
  2.          * 开始下载视频
  3.          */
  4.         public void start() {
  5.             //setThreadCount(60);
  6.             checkField();
  7.             String tsUrl = getTsUrl();
  8.             if (StringUtils.isEmpty(tsUrl))
  9.                 Log.i("不需要解密");
  10.             startDownload();
  11.         }

  12.         /**
  13.          * 下载视频
  14.          */
  15.         private void startDownload() {
  16.             //线程池
  17.             final ExecutorService fixedThreadPool = Executors.newCachedThreadPool();
  18.             int i = 0;
  19.             //如果生成目录不存在,则创建
  20.             File file1 = new File(dir);
  21.             if (!file1.exists())
  22.                 file1.mkdirs();
  23.             //执行多线程下载
  24.             for (String s : tsSet) {
  25.                 i++;
  26.                 fixedThreadPool.execute(getThread(s, i));
  27.             }
  28.             fixedThreadPool.shutdown();
  29.             //下载过程监视
  30.             new Thread(() -> {
  31.                 int consume = 0;
  32.                 //轮询是否下载成功
  33.                 while (!fixedThreadPool.isTerminated()) {
  34.                     try {
  35.                         consume++;
  36.                         BigDecimal bigDecimal = new BigDecimal(downloadBytes.toString());
  37.                         Thread.sleep(1000L);
  38.                         Log.i("已用时" + consume + "秒!\t下载速度:" + StringUtils.convertToDownloadSpeed(new BigDecimal(downloadBytes.toString()).subtract(bigDecimal), 3) + "/s");
  39.                         Log.i("\t已完成" + finishedCount + "个,还剩" + (tsSet.size() - finishedCount) + "个!");
  40.                         Log.i(new BigDecimal(finishedCount).divide(new BigDecimal(tsSet.size()), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP) + "%");
  41.                     } catch (InterruptedException e) {
  42.                         e.printStackTrace();
  43.                     }
  44.                 }
  45.                 Log.i("下载完成,正在合并文件!共" + finishedFiles.size() + "个!" + StringUtils.convertToDownloadSpeed(downloadBytes, 3));
  46.                 //开始合并视频
  47.                 mergeTs();
  48.                 //删除多余的ts片段
  49.                 deleteFiles();
  50.                 Log.i("视频合并完成,欢迎使用!");
  51.             }).start();
  52.             startListener(fixedThreadPool);
  53.         }

  54.         private void startListener(ExecutorService fixedThreadPool) {
  55.             new Thread(() -> {
  56.                 for (DownloadListener downloadListener : listenerSet)
  57.                     downloadListener.start();
  58.                 //轮询是否下载成功
  59.                 while (!fixedThreadPool.isTerminated()) {
  60.                     try {
  61.                         Thread.sleep(interval);
  62.                         for (DownloadListener downloadListener : listenerSet)
  63.                             downloadListener.process(DOWNLOADURL, finishedCount, tsSet.size(), new BigDecimal(finishedCount).divide(new BigDecimal(tsSet.size()), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP).floatValue());
  64.                     } catch (InterruptedException e) {
  65.                         e.printStackTrace();
  66.                     }
  67.                 }

  68.         /**
  69.          * 删除下载好的片段
  70.          */
  71.         private void deleteFiles() {
  72.             File file = new File(dir);
  73.             for (File f : file.listFiles()) {
  74.                 if (f.getName().endsWith(".xy") || f.getName().endsWith(".xyz"))
  75.                     f.delete();
  76.             }
  77.         }

  78.         /**
  79.          * 开启下载线程
  80.          *
  81.          * home.php?mod=space&uid=952169 urls ts片段链接
  82.          * home.php?mod=space&uid=952169 i    ts片段序号
  83.          * home.php?mod=space&uid=155549 线程
  84.          */
  85.         private Thread getThread(String urls, int i) {
  86.             return new Thread(() -> {
  87.                 int count = 1;
  88.                 HttpURLConnection httpURLConnection = null;
  89.                 //xy为未解密的ts片段,如果存在,则删除
  90.                 File file2 = new File(dir + FILESEPARATOR + i + ".xy");
  91.                 if (file2.exists())
  92.                     file2.delete();
  93.                 OutputStream outputStream = null;
  94.                 InputStream inputStream1 = null;
  95.                 FileOutputStream outputStream1 = null;
  96.                 byte[] bytes;
  97.                 try {
  98.                     bytes = BLOCKING_QUEUE.take();
  99.                 } catch (InterruptedException e) {
  100.                     bytes = new byte[Constant.BYTE_COUNT];
  101.                 }
  102.                 //重试次数判断
  103.                 while (count <= retryCount) {
  104.                     try {
  105.                         //模拟http请求获取ts片段文件
  106.                         URL url = new URL(urls);
  107.                         httpURLConnection = (HttpURLConnection) url.openConnection();
  108.                         httpURLConnection.setConnectTimeout((int) timeoutMillisecond);
  109.                         for (Map.Entry<String, Object> entry : requestHeaderMap.entrySet())
  110.                             httpURLConnection.addRequestProperty(entry.getKey(), entry.getValue().toString());
  111.                         httpURLConnection.setUseCaches(false);
  112.                         httpURLConnection.setReadTimeout((int) timeoutMillisecond);
  113.                         httpURLConnection.setDoInput(true);
  114.                         InputStream inputStream = httpURLConnection.getInputStream();
  115.                         try {
  116.                             outputStream = new FileOutputStream(file2);
  117.                         } catch (FileNotFoundException e) {
  118.                             e.printStackTrace();
  119.                             continue;
  120.                         }
  121.                         int len;
  122.                         //将未解密的ts片段写入文件
  123.                         while ((len = inputStream.read(bytes)) != -1) {
  124.                             outputStream.write(bytes, 0, len);
  125.                             synchronized (this) {
  126.                                 downloadBytes = downloadBytes.add(new BigDecimal(len));
  127.                             }
  128.                         }
  129.                         outputStream.flush();
  130.                         inputStream.close();
  131.                         inputStream1 = new FileInputStream(file2);
  132.                         int available = inputStream1.available();
  133.                         if (bytes.length < available)
  134.                             bytes = new byte[available];
  135.                         inputStream1.read(bytes);
  136.                         File file = new File(dir + FILESEPARATOR + i + ".xyz");
  137.                         outputStream1 = new FileOutputStream(file);
  138.                         //开始解密ts片段,这里我们把ts后缀改为了xyz,改不改都一样
  139.                         byte[] decrypt = decrypt(bytes, available, key, iv, method);
  140.                         if (decrypt == null)
  141.                             outputStream1.write(bytes, 0, available);
  142.                         else outputStream1.write(decrypt);
  143.                         finishedFiles.add(file);
  144.                         break;
  145.                     } catch (Exception e) {
  146.                         if (e instanceof InvalidKeyException || e instanceof InvalidAlgorithmParameterException) {
  147.                             Log.e("解密失败!");
  148.                             break;
  149.                         }
  150.                         Log.d("第" + count + "获取链接重试!\t" + urls);
  151.                         count++;
  152. //                        e.printStackTrace();
  153.                     } finally {
  154.                         try {
  155.                             if (inputStream1 != null)
  156.                                 inputStream1.close();
  157.                             if (outputStream1 != null)
  158.                                 outputStream1.close();
  159.                             if (outputStream != null)
  160.                                 outputStream.close();
  161.                             BLOCKING_QUEUE.put(bytes);
  162.                         } catch (IOException | InterruptedException e) {
  163.                             e.printStackTrace();
  164.                         }
  165.                         if (httpURLConnection != null) {
  166.                             httpURLConnection.disconnect();
  167.                         }
  168.                     }
  169.                 }
  170.                 if (count > retryCount){
  171.                     destroied();
  172.                     deleteFiles();
  173.                 }



  174.         /**
  175.          * 解密ts
  176.          *
  177.          * @param sSrc   ts文件字节数组
  178.          * @param length
  179.          * @param sKey   密钥
  180.          * [url=home.php?mod=space&uid=439838]@return[/url] 解密后的字节数组
  181.          */
  182.         private byte[] decrypt(byte[] sSrc, int length, String sKey, String iv, String method) throws Exception {
  183.             if (StringUtils.isNotEmpty(method) && !method.contains("AES"))
  184.                 throw new M3u8Exception("未知的算法!");
  185.             // 判断Key是否正确
  186.             if (StringUtils.isEmpty(sKey))
  187.                 return null;
  188.             // 判断Key是否为16位
  189.             if (sKey.length() != 16 && !isByte) {
  190.                 throw new M3u8Exception("Key长度不是16位!");
  191.             }
  192.             Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
  193.             SecretKeySpec keySpec = new SecretKeySpec(isByte ? keyBytes : sKey.getBytes(StandardCharsets.UTF_8), "AES");
  194.             byte[] ivByte;
  195.             if (iv.startsWith("0x"))
  196.                 ivByte = StringUtils.hexStringToByteArray(iv.substring(2));
  197.             else ivByte = iv.getBytes();
  198.             if (ivByte.length != 16)
  199.                 ivByte = new byte[16];
  200.             //如果m3u8有IV标签,那么IvParameterSpec构造函数就把IV标签后的内容转成字节数组传进去
  201.             AlgorithmParameterSpec paramSpec = new IvParameterSpec(ivByte);
  202.             cipher.init(Cipher.DECRYPT_MODE, keySpec, paramSpec);
  203.             return cipher.doFinal(sSrc, 0, length);
  204.         }

  205.         /**
  206.          * 字段校验
  207.          */
  208.         private void checkField() {
  209.             if ("m3u8".compareTo(MediaFormat.getMediaFormat(DOWNLOADURL)) != 0)
  210.                 throw new M3u8Exception(DOWNLOADURL + "不是一个完整m3u8链接!");
  211.             if (threadCount <= 0)
  212.                 throw new M3u8Exception("同时下载线程数只能大于0!");
  213.             if (retryCount < 0)
  214.                 throw new M3u8Exception("重试次数不能小于0!");
  215.             if (timeoutMillisecond < 0)
  216.                 throw new M3u8Exception("超时时间不能小于0!");
  217.             if (StringUtils.isEmpty(dir))
  218.                 throw new M3u8Exception("视频存储目录不能为空!");
  219.             if (StringUtils.isEmpty(fileName))
  220.                 throw new M3u8Exception("视频名称不能为空!");
  221.             finishedCount = 0;
  222.             method = "";
  223.             key = "";
  224.             isByte = false;
  225.             iv = "";
  226.             tsSet.clear();
  227.             finishedFiles.clear();
  228.             downloadBytes = new BigDecimal(0);
  229.         }

  230.         private String mergeUrl(String start, String end) {
  231.             if (end.startsWith("/"))
  232.                 end = end.replaceFirst("/", "");
  233.             for (String s1 : end.split("/")) {
  234.                 if (start.contains(s1))
  235.                     start = start.replace(s1 + "/", "");
  236.             }
  237.             return start + end;
  238.         }

  239.         public String getDOWNLOADURL() {
  240.             return DOWNLOADURL;
  241.         }

  242.         public int getThreadCount() {
  243.             return threadCount;
  244.         }

  245.         public void setThreadCount(int threadCount) {
  246.             if (BLOCKING_QUEUE.size() < threadCount) {
  247.                 for (int i = BLOCKING_QUEUE.size(); i < threadCount * Constant.FACTOR; i++) {
  248.                     try {
  249.                         BLOCKING_QUEUE.put(new byte[Constant.BYTE_COUNT]);
  250.                     } catch (InterruptedException ignored) {
  251.                     }
  252.                 }
  253.             }
  254.             this.threadCount = threadCount;
  255.         }

  256.         public int getRetryCount() {
  257.             return retryCount;
  258.         }

  259.         public void setRetryCount(int retryCount) {
  260.             this.retryCount = retryCount;
  261.         }

  262.         public long getTimeoutMillisecond() {
  263.             return timeoutMillisecond;
  264.         }

  265.         public void setTimeoutMillisecond(long timeoutMillisecond) {
  266.             this.timeoutMillisecond = timeoutMillisecond;
  267.         }

  268.         public String getDir() {
  269.             return dir;
  270.         }

  271.         public void setDir(String dir) {
  272.             this.dir = dir;
  273.         }

  274.         public String getFileName() {
  275.             return fileName;
  276.         }

  277.         public void setFileName(String fileName) {
  278.             this.fileName = fileName;
  279.         }

  280.         public int getFinishedCount() {
  281.             return finishedCount;
  282.         }

  283.         public void setLogLevel(int level) {
  284.             Log.setLevel(level);
  285.         }

  286.         public Map<String, Object> getRequestHeaderMap() {
  287.             return requestHeaderMap;
  288.         }

  289.         public void addRequestHeaderMap(Map<String, Object> requestHeaderMap) {
  290.             this.requestHeaderMap.putAll(requestHeaderMap);
  291.         }

  292.         public void setInterval(long interval) {
  293.             this.interval = interval;
  294.         }

  295.         public void addListener(DownloadListener downloadListener) {
  296.             listenerSet.add(downloadListener);
  297.         }

  298.         private M3u8Download(String DOWNLOADURL) {
  299.             this.DOWNLOADURL = DOWNLOADURL;
  300.             requestHeaderMap.put("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36");
  301.         }
  302.     }


  303. }
复制代码
开始下载
  1. public static void main(String[] args) {

  2.         String str1 = "http://aaaaaaalebu.com/video_list.php?id=1&on=90&n=10";
  3.         String result1 = HttpUtil.get(str1, CharsetUtil.CHARSET_GBK);
  4.         JSONObject object = null;
  5.         JSONObject obj = null;
  6.         JSONArray a1 = null;
  7.         String s1 = new String(result1);
  8.         object = JSON.parseObject(s1);
  9.         a1 = object.getJSONArray("list");
  10.         final boolean[] bol = {true};
  11.         boolean b = true;
  12.         int i = 0;
  13.         while (b) {
  14.             System.out.println("11>>>>>>>>>>>> ");
  15.             while (bol[0]){
  16.                 for (int x = i; i < a1.size() && bol[0] ; i++) {
  17.                     x = i;
  18.                     bol[0] = false;
  19.                     obj = a1.getJSONObject(x);
  20.                     String imgUrl = obj.getString("imgurl");
  21.                     if (imgUrl.indexOf("imgA") > 0) {
  22.                         continue;
  23.                     }
  24.                     if (!(imgUrl.indexOf("imgextra") > 0)) {
  25.                         String str = imgUrl.replaceAll("\\?", "").replaceAll(".jpg", ".m3u8").replaceAll(".gif", ".m3u8").replaceAll("img/", "video/");
  26.                         int indexb = str.lastIndexOf("/"); //去掉最后一个','号
  27.                         String stra = str.substring(0, indexb);
  28.                         int indexa = str.lastIndexOf("."); //去掉最后一个','号
  29.                         String strb = str.substring(indexb, indexa);
  30.                         String strc = str.substring(indexb, str.length());
  31.                         //String t = obj.getString("Views") + "_" + strb + ",";
  32.                         String t = obj.getString("Title") + ",";
  33.                         String sss = t.replaceAll(" ", "") + stra + strb + strc;
  34.                         // out.write(sss + "\n");

  35.                         M3u8DownloadFactory.M3u8Download m3u8Download = M3u8DownloadFactory.getInstance(stra + strb + strc);
  36.                         //设置生成目录
  37.                         m3u8Download.setDir("F://m3u8JavaTest");
  38.                         //设置视频名称
  39.                         m3u8Download.setFileName(t);
  40.                         //设置线程数
  41.                         m3u8Download.setThreadCount(500);
  42.                         //设置重试次数
  43.                         m3u8Download.setRetryCount(50);
  44.                         //设置连接超时时间(单位:毫秒)
  45.                         m3u8Download.setTimeoutMillisecond(20000L);
  46.         /*
  47.         设置日志级别
  48.         可选值:NONE INFO DEBUG ERROR
  49.         */
  50.                         m3u8Download.setLogLevel(Constant.INFO);
  51.                         //设置监听器间隔(单位:毫秒)
  52.                         m3u8Download.setInterval(500L);
  53.                         //添加额外请求头
  54.       /*  Map<String, Object> headersMap = new HashMap<>();
  55.         headersMap.put("Content-Type", "text/html;charset=utf-8");
  56.         m3u8Download.addRequestHeaderMap(headersMap);*/
  57.                         //添加监听器
  58.                         m3u8Download.addListener(new DownloadListener() {
  59.                             @Override
  60.                             public void start() {
  61.                                 System.out.println("开始下载!");
  62.                             }

  63.                             @Override
  64.                             public void process(String downloadUrl, int finished, int sum, float percent) {
  65.                                 System.out.println("下载网址:" + downloadUrl + "\t已下载" + finished + "个\t一共" + sum + "个\t已完成" + percent + "%");
  66.                             }

  67.                             @Override
  68.                             public void speed(String speedPerSecond) {
  69.                                 System.out.println("下载速度:" + speedPerSecond);
  70.                             }

  71.                             @Override
  72.                             public void end() {
  73.                                 System.out.println("下载完毕");
  74.                                 bol[0] = true;
  75.                             }
  76.                         });
  77.                         //开始下载
  78.                         m3u8Download.start();

  79.                     }
  80.                 }
  81.                b = false;
  82.                 bol[0] = false;
  83.                 System.out.println(">>>end "+i);
  84.             }
  85.             try {
  86.                 TimeUnit.SECONDS.sleep( 15 );
  87.                 System.out.println( "延时5秒,完成了");
  88.             } catch (InterruptedException e) {
  89.                 e.printStackTrace();
  90.             }
  91.         }

  92.     }
复制代码
这个是口罩封控期间无聊写的,比较随意的代码。 不要留言要域名,我也没有。
我的恩山、我的无线 The best wifi forum is right here.
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

有疑问请添加管理员QQ86788181|手机版|小黑屋|Archiver|恩山无线论坛(常州市恩山计算机开发有限公司版权所有) ( 苏ICP备05084872号 )

GMT+8, 2024-4-19 13:22

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

| 江苏省互联网有害信息举报中心 举报信箱:js12377 | @jischina.com.cn 举报电话:025-88802724 本站不良内容举报信箱:68610888@qq.com 举报电话:0519-86695797

快速回复 返回顶部 返回列表