zoukankan      html  css  js  c++  java
  • 网上的TS流视频文件下载,解密,合成一个文件的python方法(转的别人大佬的,自己存一份~~)

      1 # -*- coding:utf-8 -*- 
      2 import os
      3 import sys
      4 import requests
      5 import datetime
      6 from Crypto.Cipher import AES
      7 from binascii import b2a_hex, a2b_hex
      8 
      9 # reload(sys)
     10 # sys.setdefaultencoding('utf-8')
     11 
     12 if 1:
     13     def debug(s):
     14         print(s)
     15 else:
     16     def debug(s):
     17         pass
     18 
     19 import importlib
     20 importlib.reload(sys)
     21 
     22 def download(url, savefile_path=''):
     23     # 创建download目录
     24     download_path = os.getcwd() + "download"
     25     if not os.path.exists(download_path):
     26         os.mkdir(download_path)
     27 
     28     #新建日期文件夹,如果没有指定文件存储位置,就用年月日创建文件夹,否则用指定的文件夹
     29     if not savefile_path:
     30         savefile_path = os.path.join(download_path, datetime.datetime.now().strftime('%Y%m%d'))
     31     else:
     32         savefile_path = os.path.join(download_path, savefile_path)
     33     print("savefile_path = " + savefile_path)
     34     if not os.path.exists(savefile_path):
     35         os.mkdir(savefile_path)
     36     
     37 
     38     #如果不存在first.m3u8,就重新获取,并保存,否则证明之前已经获取过,直接读取就行了
     39     if not os.path.exists(os.path.join(download_path,'first.m3u8')):
     40         all_content = requests.get(url).text # 获取第一层M3U8文件内容
     41         with open( os.path.join(download_path,'first.m3u8'),'w' ) as f:
     42             f.write(all_content)
     43         print("save first.m3u8")
     44     else:
     45         print("first.m3u8 is exist,just read it")
     46         all_content = open( os.path.join(download_path,'first.m3u8'),'r' ).read()
     47     
     48     # 不是M3U8文件,直接报错退出
     49     if "#EXTM3U" not in all_content:
     50         raise BaseException("非M3U8的链接")
     51     # 
     52     if "EXT-X-STREAM-INF" in all_content: # 第一层
     53         # 从第一层中读取所有的文件组成行列表 file_line
     54         print("we need to get the second line")
     55         file_line = all_content.split("
    ")
     56         # 找到 .m3u8 ,拼出第二层的链接
     57         for line in file_line:
     58             if '.m3u8' in line:
     59                 url = url.rsplit("/", 1)[0] + "/" + line # 拼出第二层m3u8的URL
     60                 print("second line url = " + url)
     61                 # 没存,就存一下,同first.m3u8的逻辑
     62                 if not os.path.exists(os.path.join(download_path,'second.m3u8')):
     63                     all_content = requests.get(url).text
     64                     with open( os.path.join(download_path,'second.m3u8'),'w' ) as f:
     65                         f.write(all_content)
     66                     print("second.m3u8 has been saved")
     67                 else:
     68                     all_content = open( os.path.join(download_path,'second.m3u8'),'r' ).read()
     69                 break
     70     # 到此为止,all_content里面的内容已经更新成了包含所有文件名的最终文件
     71     #           url 更新成了下载最终m3u8的URL
     72     
     73     # 把里面的元素分割出来
     74     file_line = all_content.split("
    ")
     75 
     76     unknow = True
     77     key = ""
     78     
     79     for line in file_line:
     80         # 先找到解密key
     81         if "#EXT-X-KEY" in line: # 找解密Key
     82             method_pos = line.find("METHOD")
     83             comma_pos = line.find(",")
     84             method = line[method_pos:comma_pos].split('=')[1]
     85             print("Decode Method:", method)
     86          
     87             uri_pos = line.find("URI")
     88             quotation_mark_pos = line.rfind('"')
     89             key_path = line[uri_pos:quotation_mark_pos].split('"')[1]
     90          
     91             key_url = url.rsplit("/", 1)[0] + "/" + key_path # 拼出key解密密钥URL
     92             res = requests.get(key_url)
     93             key = res.content
     94             
     95             with open( os.path.join(download_path,'key.key'),'wb' ) as f:
     96                 f.write(key)
     97 
     98             cryptor = AES.new(key, AES.MODE_CBC, key) 
     99             print( "key:" , key)
    100             break
    101             print("you cann't see me")
    102     # 再进行下载和解密
    103     for index, line in enumerate(file_line):    # 第二层
    104         if "EXTINF" in line: # 找ts地址并下载
    105             unknow = False
    106             pd_url = url.rsplit("/", 1)[0] + "/" + file_line[index + 1] # 拼出ts片段的URL
    107          
    108             c_fule_name = file_line[index + 1].rsplit("/", 1)[-1]
    109             # 如果文件已经存在,就下一个
    110             if os.path.exists( os.path.join(savefile_path, c_fule_name) ):
    111                 print("file %s exist, next" % c_fule_name)
    112                 continue
    113             # 网络不好的时候会失败,所以重复3次
    114             for i in range(3):
    115                 # 获取视频内容
    116                 print("get video " + datetime.datetime.now().strftime('%H:%M:%S'))
    117                 res = requests.get(pd_url)
    118                 try:
    119                     if len(key): # AES 解密,有key就是需要解密
    120                         with open(os.path.join(savefile_path, c_fule_name), 'ab') as f:
    121                             f.write(cryptor.decrypt(res.content))
    122                         print(c_fule_name + " success")
    123                         break
    124                     else:  # 没有key就不需要解密了,直接保存文件就行了
    125                         with open(os.path.join(savefile_path, c_fule_name), 'ab') as f:
    126                             f.write(res.content)
    127                             f.flush()
    128                         print(c_fule_name + " success")
    129                         break
    130                 except:  # 网络不好导致下载失败,清除文件
    131                     print( str(i+1) + " download error, file: " + c_fule_name)
    132                     os.remove(os.path.join(savefile_path, c_fule_name))
    133             else:  # 下载失败,先跳过这个文件,后面重新执行的时候在重新下载
    134                 print("download file has failed 3 times, jump it")
    135                 #exit()
    136 
    137     if unknow:
    138         raise BaseException("未找到对应的下载链接")
    139     else:
    140         print( "下载完成")
    141         # merge_file(savefile_path)
    142 
    143 def merge_file(path):
    144     os.chdir(path)
    145     cmd = "copy /b * new.ts"
    146     #os.system(cmd)
    147     #os.system('del /Q *.ts')
    148     #os.system('del /Q *.mp4')
    149     #os.rename("new.tmp", "new.mp4")
    150  
    151 if __name__ == '__main__':
    152     url = input("please input the url of index.m3u8 file:
    ")
    153     savefile_path = input("give me a dir name to save all the video:
    (or you can just press Enter and I will create one for you)
    ")
    154     # url = r''
    155     # savefile_path = r''
    156     download(url,savefile_path)
  • 相关阅读:
    教你认识Git
    jmeter跨线程组传递token
    win10企业版激活步骤
    jmeter录制浏览器Https请求
    win10程序无法正常启动0xc0000142
    PPT页面切换动画
    PPT页面动画制作
    查询一门成绩高于另一门课程的学生信息
    MongoDB固定集合-capped collection
    CoronaSDK场景管理库:Composer library (中)
  • 原文地址:https://www.cnblogs.com/gsp1004/p/11337433.html
Copyright © 2011-2022 走看看