Python下载m3u8视频,支持多线程,断点下载(也可以修改后下载其他类型视频)
先上github地址:
https://github.com/tosobright/m3u8-Downloader
1.获取m3u8列表
- flist = []
- key = ''
- all_content = requests.get(url).text
- if "#EXTM3U" not in all_content:
- print u"Not m3u8" + all_content.decode('GBK')
- if "EXT-X-STREAM-INF" in all_content: # 第一层
- file_line = all_content.split("\n")
- for line in file_line:
- if '.m3u8' in line:
- url = url.rsplit("/", 1)[0] + "/" + line # 拼出第二层m3u8的URL
- all_content = requests.get(url).text
- file_line = all_content.split("\n")
- for item in file_line:
- if "#" not in item:
- if item != "":
- flist.append(url.rsplit("/", 1)[0] + "/" + item)
- else:
- if "#EXT-X-KEY" in item: # 找解密Key
- method_pos = item.find("METHOD")
- comma_pos = item.find(",")
- method = item[method_pos:comma_pos].split('=')[1]
- print u"Decode Method:", method
- uri_pos = item.find("URI")
- quotation_mark_pos = line.rfind('"')
- key_path = item[uri_pos:quotation_mark_pos].split('"')[
- 1]
- key_url = url.rsplit(
- "/", 1)[0] + "/" + key_path # 拼出key解密密钥URL
- res = requests.get(key_url)
- key = res.content
- print u"key:", key
- return flist, key
2.根据解析的m3u8地址进行下载,并记录下当前下载的进度点
- length = len(playlists)
- if len(key): # AES 解密
- cryptor = AES.new(key, AES.MODE_CBC, key)
- headers = {
- "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.146 Safari/537.36"}
- # 增加断点续传
- logfilename = os.path.split(filepath)[1].split('.')[0] + '.lf'
- logfile = os.path.split(filepath)[0] + '\\' + logfilename
- if os.path.exists(logfile):
- with open(logfile, 'r') as f:
- DownLoadedIndex = int(f.read())
- else:
- DownLoadedIndex = -1
- for index, url in enumerate(playlists):
- # 是否下载判定
- if index > DownLoadedIndex:
- notOK = True
- while notOK:
- try:
- res = requests.get(url, timeout=5, headers=headers)
- #print res.content
- # s.decode('GBK')
- if res.status_code == 200:
- print (os.path.split(filepath)[
- 1] + " : " + str(index)+"|"+str(length-1) + " ").decode('GBK')
- if len(key): # AES 解密
- with open(filepath, 'ab') as f:
- f.write(cryptor.decrypt(res.content))
- else:
- with open(filepath, 'ab') as f:
- f.write(res.content)
- time.sleep(1)
- notOK = False
- with open(logfile, 'w') as f:
- f.write(str(index))
- except Exception as e:
- print (os.path.split(filepath)[
- 1] + ' retry...' + str(e)).decode('GBK')
- time.sleep(5)
3.开启多线程进行下载
- playlists, key = GetPlayLists(url)
- if len(playlists) != 0:
- print 'Total Length:', len(playlists)
- if len(playlists) <= process:
- process = len(playlists)
- splitlength = len(playlists)/process + 1
- splitlist = [playlists[i:i+splitlength]
- for i in range(0, len(playlists), splitlength)]
- print splitlength, len(splitlist)
- param = []
- for index, lists in enumerate(splitlist):
- fp = filepath.rsplit("\", 1)[
- 0] + "\" + str(index).zfill(3)+filepath.rsplit("\", 1)[1]
- dict = {'filepath': fp, 'playlists': lists, 'key': key}
- param.append((None, dict))
- pool = threadpool.ThreadPool(process)
- requests = threadpool.makeRequests(download, param)
- [pool.putRequest(req) for req in requests]
- pool.wait()
- pool.dismissWorkers(process)
- return True
- else:
- return False
|