欢迎使用CSDN-markdown编辑器123
引言
手头上有一个m3u8下载视频的java源码,但想转为python语言用来学习。我先看原java版的m3u8源码先撸了一遍,然后开发将他转了python版。
原java版
Main.java
package com.hhf.m3u8;
import java.io.File;
import java.io.IOException;
import static com.hhf.m3u8.Config.getConfig;
import static com.hhf.util.StringUtil.isMessyCode;
public class Main
{
public static void main(String[] args) {
String resource = getConfig("download.resource");
String rootPath = getConfig("save.path");
String ffmpeg= getConfig("ffmpeg.path");
if (isMessyCode(resource) || isMessyCode(rootPath)) {
System.out.println("存在乱码");
return;
}
String[] ss = resource.split(",");
System.out.println();
String fileName = ss[0];
String m3u8Url = ss[1];
M3U8Downloader downloader = new M3U8Downloader(ffmpeg, rootPath, fileName, m3u8Url);
boolean isSuccess = downloader.start();
try {
if(isSuccess) {
System.out.println("---------Compile MP4-------------");
downloader.composeFile(downloader.getIndexFile());
}
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("-------- DONE. ---------");
System.exit(0);
}
}
转换类(M3U8Downloader.java)
package com.hhf.m3u8;
import com.hhf.util.HttpsUtil;
import com.hhf.util.IOUtil;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class M3U8Downloader {
String rootFile;
String fileName;
String m3u8Url;
String ffmpeg;
String indexFile;
LinkedList<Download> downloadList = new LinkedList();
LinkedList<Download> successList = new LinkedList();
class Download {
String url;
File file;
int downloadTime = 0;
public Download(String url, File file) {
this.url = url;
this.file = file;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public File getFile() {
return file;
}
public void setFile(File file) {
this.file = file;
}
public int getDownloadTime() {
return downloadTime;
}
public void setDownloadTime(int downloadTime) {
this.downloadTime = downloadTime;
}
}
class DownloadNet implements Runnable {
@Override
public void run() {
while (!downloadList.isEmpty()) {
Download download;
synchronized (downloadList) {
if(downloadList.size()>0) {
download = downloadList.removeFirst();
}
else{
continue;
}
System.out.println("------> QUERY SIZE:" + downloadList.size() );
}
try {
if (download.file.exists()) {
System.out.println(download.file.getCanonicalPath() + " file exist, ignore download" );
continue;
}
System.out.println("Thread " + Thread.currentThread().getName() + " " + Thread.currentThread().getId() + " " + download.getUrl());
File tmp = new File(download.file.getParent(), download.file.getName() + ".download");
boolean success = false;
InputStream inStream = null;
FileOutputStream fs = null;
try {
inStream = new HttpsUtil().getInputStream(download.getUrl());
fs = new FileOutputStream(tmp);
int byteread = 0;
byte[] buffer = new byte[1204];
while ((byteread = inStream.read(buffer)) != -1) {
fs.write(buffer, 0, byteread);
}
success = true;
}
finally {
IOUtil.close(inStream);
IOUtil.close(fs);
}
if (success) {
if (tmp.renameTo(download.file)) {
synchronized (successList) {
successList.add(download);
}
System.out.println(download.url + " success download to " + download.file.getCanonicalPath());
}
} else {
System.out.println(download.url + " download failure. ");
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
if(download.downloadTime++<5){
synchronized (downloadList){
downloadList.add(download);
}
}
}
}
}
}
public M3U8Downloader(String ffmpeg, String rootFile, String fileName, String m3u8Url) {
this.rootFile = rootFile;
this.fileName = fileName;
this.m3u8Url = m3u8Url;
this.ffmpeg = ffmpeg;
this.indexFile = (rootFile + File.separator + fileName + File.separator + "index.m3u8").replaceAll("/", "\\\\");
}
public String getIndexFile(){
return this.indexFile;
}
public String getUrlContent(String urlStr) throws Exception {
// URL url = new URL(urlStr);
HttpsUtil util = new HttpsUtil();
return IOUtil.read(util.getInputStream(urlStr));
}
public boolean start() {
try {
File fileDir = new File(rootFile, fileName);
if (!fileDir.exists()) {
if (!fileDir.mkdirs()) {
throw new IOException("Create directory " + fileDir.getCanonicalPath() + " failure.");
}
}
String indexName = getIndexName(m3u8Url);
File indexFile = new File(fileDir, indexName);
String content;
if (!indexFile.exists()) {
System.out.println("Not found index file " + indexFile.getCanonicalPath() + ",downloading.");
content = getUrlContent(m3u8Url);
if (saveFile(indexFile, content.getBytes())) {
System.out.println("Saved file:" + indexFile.getCanonicalPath());
}
} else {
content = IOUtil.read(new FileInputStream(indexFile));
}
String baseUrl = getBaseUrl(m3u8Url);
List<String> uri = analysisIndex(content);
return download(baseUrl, fileDir, uri);
} catch (Exception ex) {
ex.printStackTrace();
return false;
}
}
public String getBaseUrl(String url) {
return url.substring(0, url.lastIndexOf("/") + 1);
}
public boolean saveFile(File file, byte[] data) {
try (FileOutputStream fs = new FileOutputStream(file)) {
fs.write(data);
return true;
} catch (FileNotFoundException e) {
e.printStackTrace();
return false;
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
public String getIndexName(String url) {
int pos = url.lastIndexOf("/");
return url.substring(pos + 1);
}
public boolean download(String baseUrl, File fileDir, List<String> ls) {
int threadCount = 10;
ExecutorService service = Executors.newFixedThreadPool(threadCount);
for (String s : ls) {
downloadList.add(new Download(baseUrl + s, new File(fileDir, s)));
}
for (int i = 0; i < threadCount; i++) {
service.execute(new DownloadNet());
}
boolean isSuccess = true;
try {
service.shutdown();
if (!service.awaitTermination(3600000, TimeUnit.SECONDS)) { //超时后直接关闭
service.shutdownNow();
isSuccess = true;
}
} catch (InterruptedException e) { //awaitTermination 出现中断异常也将触发关闭
service.shutdownNow();
isSuccess = false;
}
System.out.println("-------- download finish. ---------");
return isSuccess;
}
public List analysisIndex(String content) throws Exception {
Pattern pattern = Pattern.compile(".*ts");
Matcher ma = pattern.matcher(content);
List<String> list = new ArrayList<String>();
while (ma.find()) {
list.add(ma.group());
}
return list;
}
public String composeFile(String index2) throws IOException {
String ffmpegCmds = (ffmpeg + " -allowed_extensions ALL -i " + index2 + " -c copy " + rootFile + File.separator + fileName + ".mp4").replaceAll("\\\\", "/").replaceAll("//", "/");
System.out.println("CMD:" + ffmpegCmds);
Process process = null;
Runtime run = null;
run = Runtime.getRuntime();
long start = System.currentTimeMillis();
try {
Process p = run.exec(ffmpegCmds);
//释放进程
p.getOutputStream().close();
p.getInputStream().close();
p.getErrorStream().close();
p.waitFor();
long end = System.currentTimeMillis();
System.out.println(ffmpegCmds + " costs:" + (end - start) + "ms");
} catch (Exception e) {
System.out.println("--- FFmpeg命令执行出错! --- 出错信息: " + e.getMessage());
return null;
} finally {
if (null != process) {
process.destroy();
}
}
return "--";
}
}
Config.java
package com.hhf.m3u8;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Properties;
public class Config
{
private static Properties properties;
public static String getConfig(String key){
if(properties == null){
properties = new Properties();
try(InputStreamReader bis = new InputStreamReader(Main.class.getResourceAsStream("/app.properties"), "UTF-8")) {
properties.load(bis);
}
catch (IOException ex){
throw new RuntimeException("Not found the app.properties file.");
}
}
String v = (String) properties.get(key);
if(v == null){
throw new RuntimeException("Not found the key:" + key);
}
return v;
}
}
源码并不复杂,但我是java出身的我,如果转python呢?
参考
python3爬虫(3)下载流媒体m3u8
- https://blog.csdn.net/liujiayu2/article/details/86083400
java转python代码
- https://blog.csdn.net/u011546806/article/details/45074557?utm_medium=distribute.pc_relevant.none-task-blog-baidujs-2
python与mysql(一)
python 下载 M3U8 视频
- https://blog.csdn.net/lswzw/article/details/100105646