|
隔壁论坛也是我发布的,但是非注册用户可能看不到。在恩山再发一贴,如有不符合版规还清管理员移动到对应板块,谢谢。
文中域名均已脱敏,且原域名都失效,不要回复要域名的。楼主也想知道新域名呢
先api抓取数据,抓换成iptv可以播放的看下在线的
- public static void main(String[] args) {
- /*String s = "145_/hd_0152,https://aaaaaaaaa.com/video/12/hd_0152/hd_0152.m3u8";
- int a = s.lastIndexOf("/"); //去掉最后一个','号
- String s1 = s.substring(a + 1, s.length());
- String hd = s.substring(a + 1, a + 3);
- System.out.println("" + hd);
- int b = s.lastIndexOf("."); //去掉最后一个','号
- String tvgid = s.substring(a + 1, b);
- int c = s.lastIndexOf("http"); //去掉最后一个','号
- System.out.println(s.substring(c, s.length()));
- String img = ""+s.substring(c, a).replaceAll("video","img")+".jpg";
- String m3 = "#EXTINF:-1 tvg-id="%s" tvg-name="%s" tvg-logo="%s" tvg-language="Chinese" tvg-country="CN" group-title="",%s";
- String m = String.format(m3, tvgid, s1,img, s1);
- System.out.println(m);*/
- String url = "http://aaaaaaalebu.com/video_list.php?id=17&on=20&n=10";
- String jsonStr = http(url);
- json(jsonStr, "04");
- StringBuilder builder = readFileByBytes("C:/upload/aaa/04.txt");
- if (builder != null) {
- try {
- File file1 = new File("C:\\upload\\aaa\\04m3.txt");
- BufferedWriter bw = new BufferedWriter(new FileWriter(file1));
- bw.write(builder.toString());
- bw.flush();
- bw.close();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
- //组合出下面的 IPTV格式
- #EXTM3U
- #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吧。先写个下载工具类
- /**
- * 开始下载视频
- */
- public void start() {
- //setThreadCount(60);
- checkField();
- String tsUrl = getTsUrl();
- if (StringUtils.isEmpty(tsUrl))
- Log.i("不需要解密");
- startDownload();
- }
- /**
- * 下载视频
- */
- private void startDownload() {
- //线程池
- final ExecutorService fixedThreadPool = Executors.newCachedThreadPool();
- int i = 0;
- //如果生成目录不存在,则创建
- File file1 = new File(dir);
- if (!file1.exists())
- file1.mkdirs();
- //执行多线程下载
- for (String s : tsSet) {
- i++;
- fixedThreadPool.execute(getThread(s, i));
- }
- fixedThreadPool.shutdown();
- //下载过程监视
- new Thread(() -> {
- int consume = 0;
- //轮询是否下载成功
- while (!fixedThreadPool.isTerminated()) {
- try {
- consume++;
- BigDecimal bigDecimal = new BigDecimal(downloadBytes.toString());
- Thread.sleep(1000L);
- Log.i("已用时" + consume + "秒!\t下载速度:" + StringUtils.convertToDownloadSpeed(new BigDecimal(downloadBytes.toString()).subtract(bigDecimal), 3) + "/s");
- Log.i("\t已完成" + finishedCount + "个,还剩" + (tsSet.size() - finishedCount) + "个!");
- 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) + "%");
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- Log.i("下载完成,正在合并文件!共" + finishedFiles.size() + "个!" + StringUtils.convertToDownloadSpeed(downloadBytes, 3));
- //开始合并视频
- mergeTs();
- //删除多余的ts片段
- deleteFiles();
- Log.i("视频合并完成,欢迎使用!");
- }).start();
- startListener(fixedThreadPool);
- }
- private void startListener(ExecutorService fixedThreadPool) {
- new Thread(() -> {
- for (DownloadListener downloadListener : listenerSet)
- downloadListener.start();
- //轮询是否下载成功
- while (!fixedThreadPool.isTerminated()) {
- try {
- Thread.sleep(interval);
- for (DownloadListener downloadListener : listenerSet)
- 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());
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- /**
- * 删除下载好的片段
- */
- private void deleteFiles() {
- File file = new File(dir);
- for (File f : file.listFiles()) {
- if (f.getName().endsWith(".xy") || f.getName().endsWith(".xyz"))
- f.delete();
- }
- }
- /**
- * 开启下载线程
- *
- * home.php?mod=space&uid=952169 urls ts片段链接
- * home.php?mod=space&uid=952169 i ts片段序号
- * home.php?mod=space&uid=155549 线程
- */
- private Thread getThread(String urls, int i) {
- return new Thread(() -> {
- int count = 1;
- HttpURLConnection httpURLConnection = null;
- //xy为未解密的ts片段,如果存在,则删除
- File file2 = new File(dir + FILESEPARATOR + i + ".xy");
- if (file2.exists())
- file2.delete();
- OutputStream outputStream = null;
- InputStream inputStream1 = null;
- FileOutputStream outputStream1 = null;
- byte[] bytes;
- try {
- bytes = BLOCKING_QUEUE.take();
- } catch (InterruptedException e) {
- bytes = new byte[Constant.BYTE_COUNT];
- }
- //重试次数判断
- while (count <= retryCount) {
- try {
- //模拟http请求获取ts片段文件
- URL url = new URL(urls);
- httpURLConnection = (HttpURLConnection) url.openConnection();
- httpURLConnection.setConnectTimeout((int) timeoutMillisecond);
- for (Map.Entry<String, Object> entry : requestHeaderMap.entrySet())
- httpURLConnection.addRequestProperty(entry.getKey(), entry.getValue().toString());
- httpURLConnection.setUseCaches(false);
- httpURLConnection.setReadTimeout((int) timeoutMillisecond);
- httpURLConnection.setDoInput(true);
- InputStream inputStream = httpURLConnection.getInputStream();
- try {
- outputStream = new FileOutputStream(file2);
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- continue;
- }
- int len;
- //将未解密的ts片段写入文件
- while ((len = inputStream.read(bytes)) != -1) {
- outputStream.write(bytes, 0, len);
- synchronized (this) {
- downloadBytes = downloadBytes.add(new BigDecimal(len));
- }
- }
- outputStream.flush();
- inputStream.close();
- inputStream1 = new FileInputStream(file2);
- int available = inputStream1.available();
- if (bytes.length < available)
- bytes = new byte[available];
- inputStream1.read(bytes);
- File file = new File(dir + FILESEPARATOR + i + ".xyz");
- outputStream1 = new FileOutputStream(file);
- //开始解密ts片段,这里我们把ts后缀改为了xyz,改不改都一样
- byte[] decrypt = decrypt(bytes, available, key, iv, method);
- if (decrypt == null)
- outputStream1.write(bytes, 0, available);
- else outputStream1.write(decrypt);
- finishedFiles.add(file);
- break;
- } catch (Exception e) {
- if (e instanceof InvalidKeyException || e instanceof InvalidAlgorithmParameterException) {
- Log.e("解密失败!");
- break;
- }
- Log.d("第" + count + "获取链接重试!\t" + urls);
- count++;
- // e.printStackTrace();
- } finally {
- try {
- if (inputStream1 != null)
- inputStream1.close();
- if (outputStream1 != null)
- outputStream1.close();
- if (outputStream != null)
- outputStream.close();
- BLOCKING_QUEUE.put(bytes);
- } catch (IOException | InterruptedException e) {
- e.printStackTrace();
- }
- if (httpURLConnection != null) {
- httpURLConnection.disconnect();
- }
- }
- }
- if (count > retryCount){
- destroied();
- deleteFiles();
- }
- /**
- * 解密ts
- *
- * @param sSrc ts文件字节数组
- * @param length
- * @param sKey 密钥
- * [url=home.php?mod=space&uid=439838]@return[/url] 解密后的字节数组
- */
- private byte[] decrypt(byte[] sSrc, int length, String sKey, String iv, String method) throws Exception {
- if (StringUtils.isNotEmpty(method) && !method.contains("AES"))
- throw new M3u8Exception("未知的算法!");
- // 判断Key是否正确
- if (StringUtils.isEmpty(sKey))
- return null;
- // 判断Key是否为16位
- if (sKey.length() != 16 && !isByte) {
- throw new M3u8Exception("Key长度不是16位!");
- }
- Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
- SecretKeySpec keySpec = new SecretKeySpec(isByte ? keyBytes : sKey.getBytes(StandardCharsets.UTF_8), "AES");
- byte[] ivByte;
- if (iv.startsWith("0x"))
- ivByte = StringUtils.hexStringToByteArray(iv.substring(2));
- else ivByte = iv.getBytes();
- if (ivByte.length != 16)
- ivByte = new byte[16];
- //如果m3u8有IV标签,那么IvParameterSpec构造函数就把IV标签后的内容转成字节数组传进去
- AlgorithmParameterSpec paramSpec = new IvParameterSpec(ivByte);
- cipher.init(Cipher.DECRYPT_MODE, keySpec, paramSpec);
- return cipher.doFinal(sSrc, 0, length);
- }
- /**
- * 字段校验
- */
- private void checkField() {
- if ("m3u8".compareTo(MediaFormat.getMediaFormat(DOWNLOADURL)) != 0)
- throw new M3u8Exception(DOWNLOADURL + "不是一个完整m3u8链接!");
- if (threadCount <= 0)
- throw new M3u8Exception("同时下载线程数只能大于0!");
- if (retryCount < 0)
- throw new M3u8Exception("重试次数不能小于0!");
- if (timeoutMillisecond < 0)
- throw new M3u8Exception("超时时间不能小于0!");
- if (StringUtils.isEmpty(dir))
- throw new M3u8Exception("视频存储目录不能为空!");
- if (StringUtils.isEmpty(fileName))
- throw new M3u8Exception("视频名称不能为空!");
- finishedCount = 0;
- method = "";
- key = "";
- isByte = false;
- iv = "";
- tsSet.clear();
- finishedFiles.clear();
- downloadBytes = new BigDecimal(0);
- }
- private String mergeUrl(String start, String end) {
- if (end.startsWith("/"))
- end = end.replaceFirst("/", "");
- for (String s1 : end.split("/")) {
- if (start.contains(s1))
- start = start.replace(s1 + "/", "");
- }
- return start + end;
- }
- public String getDOWNLOADURL() {
- return DOWNLOADURL;
- }
- public int getThreadCount() {
- return threadCount;
- }
- public void setThreadCount(int threadCount) {
- if (BLOCKING_QUEUE.size() < threadCount) {
- for (int i = BLOCKING_QUEUE.size(); i < threadCount * Constant.FACTOR; i++) {
- try {
- BLOCKING_QUEUE.put(new byte[Constant.BYTE_COUNT]);
- } catch (InterruptedException ignored) {
- }
- }
- }
- this.threadCount = threadCount;
- }
- public int getRetryCount() {
- return retryCount;
- }
- public void setRetryCount(int retryCount) {
- this.retryCount = retryCount;
- }
- public long getTimeoutMillisecond() {
- return timeoutMillisecond;
- }
- public void setTimeoutMillisecond(long timeoutMillisecond) {
- this.timeoutMillisecond = timeoutMillisecond;
- }
- public String getDir() {
- return dir;
- }
- public void setDir(String dir) {
- this.dir = dir;
- }
- public String getFileName() {
- return fileName;
- }
- public void setFileName(String fileName) {
- this.fileName = fileName;
- }
- public int getFinishedCount() {
- return finishedCount;
- }
- public void setLogLevel(int level) {
- Log.setLevel(level);
- }
- public Map<String, Object> getRequestHeaderMap() {
- return requestHeaderMap;
- }
- public void addRequestHeaderMap(Map<String, Object> requestHeaderMap) {
- this.requestHeaderMap.putAll(requestHeaderMap);
- }
- public void setInterval(long interval) {
- this.interval = interval;
- }
- public void addListener(DownloadListener downloadListener) {
- listenerSet.add(downloadListener);
- }
- private M3u8Download(String DOWNLOADURL) {
- this.DOWNLOADURL = DOWNLOADURL;
- 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");
- }
- }
- }
复制代码 开始下载
- public static void main(String[] args) {
- String str1 = "http://aaaaaaalebu.com/video_list.php?id=1&on=90&n=10";
- String result1 = HttpUtil.get(str1, CharsetUtil.CHARSET_GBK);
- JSONObject object = null;
- JSONObject obj = null;
- JSONArray a1 = null;
- String s1 = new String(result1);
- object = JSON.parseObject(s1);
- a1 = object.getJSONArray("list");
- final boolean[] bol = {true};
- boolean b = true;
- int i = 0;
- while (b) {
- System.out.println("11>>>>>>>>>>>> ");
- while (bol[0]){
- for (int x = i; i < a1.size() && bol[0] ; i++) {
- x = i;
- bol[0] = false;
- obj = a1.getJSONObject(x);
- String imgUrl = obj.getString("imgurl");
- if (imgUrl.indexOf("imgA") > 0) {
- continue;
- }
- if (!(imgUrl.indexOf("imgextra") > 0)) {
- String str = imgUrl.replaceAll("\\?", "").replaceAll(".jpg", ".m3u8").replaceAll(".gif", ".m3u8").replaceAll("img/", "video/");
- int indexb = str.lastIndexOf("/"); //去掉最后一个','号
- String stra = str.substring(0, indexb);
- int indexa = str.lastIndexOf("."); //去掉最后一个','号
- String strb = str.substring(indexb, indexa);
- String strc = str.substring(indexb, str.length());
- //String t = obj.getString("Views") + "_" + strb + ",";
- String t = obj.getString("Title") + ",";
- String sss = t.replaceAll(" ", "") + stra + strb + strc;
- // out.write(sss + "\n");
- M3u8DownloadFactory.M3u8Download m3u8Download = M3u8DownloadFactory.getInstance(stra + strb + strc);
- //设置生成目录
- m3u8Download.setDir("F://m3u8JavaTest");
- //设置视频名称
- m3u8Download.setFileName(t);
- //设置线程数
- m3u8Download.setThreadCount(500);
- //设置重试次数
- m3u8Download.setRetryCount(50);
- //设置连接超时时间(单位:毫秒)
- m3u8Download.setTimeoutMillisecond(20000L);
- /*
- 设置日志级别
- 可选值:NONE INFO DEBUG ERROR
- */
- m3u8Download.setLogLevel(Constant.INFO);
- //设置监听器间隔(单位:毫秒)
- m3u8Download.setInterval(500L);
- //添加额外请求头
- /* Map<String, Object> headersMap = new HashMap<>();
- headersMap.put("Content-Type", "text/html;charset=utf-8");
- m3u8Download.addRequestHeaderMap(headersMap);*/
- //添加监听器
- m3u8Download.addListener(new DownloadListener() {
- @Override
- public void start() {
- System.out.println("开始下载!");
- }
- @Override
- public void process(String downloadUrl, int finished, int sum, float percent) {
- System.out.println("下载网址:" + downloadUrl + "\t已下载" + finished + "个\t一共" + sum + "个\t已完成" + percent + "%");
- }
- @Override
- public void speed(String speedPerSecond) {
- System.out.println("下载速度:" + speedPerSecond);
- }
- @Override
- public void end() {
- System.out.println("下载完毕");
- bol[0] = true;
- }
- });
- //开始下载
- m3u8Download.start();
- }
- }
- b = false;
- bol[0] = false;
- System.out.println(">>>end "+i);
- }
- try {
- TimeUnit.SECONDS.sleep( 15 );
- System.out.println( "延时5秒,完成了");
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
复制代码 这个是口罩封控期间无聊写的,比较随意的代码。 不要留言要域名,我也没有。
|
|