Python下载m3u8视频

[复制链接]
2117|1
 楼主| taosha126 发表于 2019-7-25 10:52 | 显示全部楼层 |阅读模式
Python下载m3u8视频,支持多线程,断点下载(也可以修改后下载其他类型视频)
先上github地址:
https://github.com/tosobright/m3u8-Downloader

1.获取m3u8列表
  1. flist = []
  2.     key = ''

  3.     all_content = requests.get(url).text

  4.     if "#EXTM3U" not in all_content:
  5.         print u"Not m3u8" + all_content.decode('GBK')

  6.     if "EXT-X-STREAM-INF" in all_content:  # 第一层
  7.         file_line = all_content.split("\n")
  8.         for line in file_line:
  9.             if '.m3u8' in line:
  10.                 url = url.rsplit("/", 1)[0] + "/" + line  # 拼出第二层m3u8的URL
  11.                 all_content = requests.get(url).text
  12.                 file_line = all_content.split("\n")

  13.                 for item in file_line:
  14.                     if "#" not in item:
  15.                         if item != "":
  16.                             flist.append(url.rsplit("/", 1)[0] + "/" + item)
  17.                     else:
  18.                         if "#EXT-X-KEY" in item:  # 找解密Key
  19.                             method_pos = item.find("METHOD")
  20.                             comma_pos = item.find(",")
  21.                             method = item[method_pos:comma_pos].split('=')[1]
  22.                             print u"Decode Method:", method

  23.                             uri_pos = item.find("URI")
  24.                             quotation_mark_pos = line.rfind('"')
  25.                             key_path = item[uri_pos:quotation_mark_pos].split('"')[
  26.                                 1]

  27.                             key_url = url.rsplit(
  28.                                 "/", 1)[0] + "/" + key_path  # 拼出key解密密钥URL
  29.                             res = requests.get(key_url)
  30.                             key = res.content
  31.                             print u"key:", key

  32.     return flist, key

2.根据解析的m3u8地址进行下载,并记录下当前下载的进度点

  1. length = len(playlists)
  2.     if len(key):  # AES 解密
  3.         cryptor = AES.new(key, AES.MODE_CBC, key)
  4.     headers = {
  5.         "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.146 Safari/537.36"}

  6.     # 增加断点续传
  7.     logfilename = os.path.split(filepath)[1].split('.')[0] + '.lf'
  8.     logfile = os.path.split(filepath)[0] + '\\' + logfilename
  9.     if os.path.exists(logfile):
  10.         with open(logfile, 'r') as f:
  11.             DownLoadedIndex = int(f.read())
  12.     else:
  13.         DownLoadedIndex = -1

  14.     for index, url in enumerate(playlists):
  15.         # 是否下载判定
  16.         if index > DownLoadedIndex:
  17.             notOK = True
  18.             while notOK:
  19.                 try:
  20.                     res = requests.get(url, timeout=5, headers=headers)
  21.                     #print res.content
  22.                     # s.decode('GBK')
  23.                     if res.status_code == 200:
  24.                         print (os.path.split(filepath)[
  25.                             1] + " : " + str(index)+"|"+str(length-1) + "   ").decode('GBK')
  26.                         if len(key):  # AES 解密
  27.                             with open(filepath, 'ab') as f:
  28.                                 f.write(cryptor.decrypt(res.content))
  29.                         else:
  30.                             with open(filepath, 'ab') as f:
  31.                                 f.write(res.content)
  32.                         time.sleep(1)
  33.                         notOK = False
  34.                         with open(logfile, 'w') as f:
  35.                             f.write(str(index))

  36.                 except Exception as e:
  37.                     print (os.path.split(filepath)[
  38.                         1] + '  retry...' + str(e)).decode('GBK')
  39.                     time.sleep(5)
3.开启多线程进行下载
  1. playlists, key = GetPlayLists(url)
  2.     if len(playlists) != 0:
  3.         print 'Total Length:', len(playlists)

  4.         if len(playlists) <= process:
  5.             process = len(playlists)

  6.         splitlength = len(playlists)/process + 1
  7.         splitlist = [playlists[i:i+splitlength]
  8.                      for i in range(0, len(playlists), splitlength)]
  9.         print splitlength, len(splitlist)
  10.         param = []
  11.         for index, lists in enumerate(splitlist):
  12.             fp = filepath.rsplit("\", 1)[
  13.                 0] + "\" + str(index).zfill(3)+filepath.rsplit("\", 1)[1]
  14.             dict = {'filepath': fp, 'playlists': lists, 'key': key}
  15.             param.append((None, dict))

  16.         pool = threadpool.ThreadPool(process)
  17.         requests = threadpool.makeRequests(download, param)
  18.         [pool.putRequest(req) for req in requests]
  19.         pool.wait()
  20.         pool.dismissWorkers(process)

  21.         return True
  22.     else:
  23.         return False


gaoyang9992006 发表于 2019-8-31 23:37 | 显示全部楼层
手机视频一般用的这个传输的,是个简单的文本文件,然后不知道视频文件是怎么分存的。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2

主题

18

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部