ts 视频下载[通俗易懂]

ts 视频下载[通俗易懂]importurllib.requestimportrequests,os,threadingfromCrypto.CipherimportAESfromsrc.Pacho.moviePa.tsdownloadimportaes_decodeclassm3u8down(object):def__init__(self,url,listheaders,dicheaders):self.url=url#这里的url是index.m3.

大家好,又见面了,我是你们的朋友全栈君。

import urllib.request
import requests, os, threading
from Crypto.Cipher import AES
from src.Pacho.moviePa.tsdownload import aes_decode

class m3u8down(object):
    def __init__(self, url, listheaders, dicheaders):
        self.url = url  # 这里的url是index.m3u8地址
        self.headers = listheaders
        self.header = dicheaders
        self.ts_parts = []
        self.down_path = 'D:/workspace/download/Mp4'
        self.tsthreads = []
        self.key = None

    def aes_decode(self, data, key):
        """AES解密
        :param key:  密钥(16.32)一般16的倍数
        :param data:  要解密的数据
        :return:  处理好的数据
        """
        cryptor = AES.new(key, AES.MODE_CBC, key)
        plain_text = cryptor.decrypt(data)
        return plain_text.rstrip(b'\0')  # .decode("utf-8")

    def to_ts(self):
        requests.packages.urllib3.disable_warnings()
        content_all = requests.get(self.url, verify=False, timeout=200).text
        if "#EXTM3U" not in content_all:
            raise BaseException("非M3U8的链接")
        if "EXT-X-VERSION" in content_all:
            file_line = content_all.split("\n")
            # print(file_line)
            self.get_tsurls(self.url, file_line)

    def get_tsurls(self, m3u8url, lines):
        for index, line in enumerate(lines):  # m3u8文件中有ts,获取ts地址并添加索引
            if "EXTINF" in line:  # 找ts地址
                if "/" not in lines[index + 1]:  # 判断.ts是否是路径 'DjbgADY7468014.ts' or '/20181221/.../VRYKBY4319009.ts'
                    ts_url = m3u8url.rsplit("/", 1)[0] + "/" + lines[index + 1]  # 拼出ts片段的URL
                else:
                    ts_url = m3u8url.rsplit("/", 1)[0] + "/" + lines[index + 1].rsplit("/", 1)[-1]  # 拼出ts片段的URL
                self.ts_parts.append(ts_url)
            if "#EXT-X-KEY" in line:
                # #EXT-X-KEY:METHOD=AES-128,URI="encryption.key"
                key_url = m3u8url.rsplit("/", 1)[0] + "/" + line.split('"')[1]
                self.key = requests.get(url=key_url, timeout=120, headers=self.header).content  # 获取秘钥

    def load_ts(self, ts_url, files, count):
        if self.key:
            self.auto_keydown(ts_url, files, self.header, self.key)
        else:
            self.auto_down(ts_url, files, self.headers)
        print('第 %d/%d 个文件下载完成, 下载地址是%s' % (count, len(self.ts_parts), ts_url))
        count += 1


    def auto_down(self, url, filename, headers):  # 下载失败后,自调用从新下载
        try:
            opener = urllib.request.build_opener()  # 创建opener对象
            opener.addheaders = self.headers
            urllib.request.install_opener(opener)  # 将opener对象装入urllib.request
            urllib.request.urlretrieve(url, filename)
        except Exception as ex:
            # print(ex.args, url)
            return self.auto_down(url, filename, headers)

    def auto_keydown(self, url, filename, headers, key):  # 下载失败后,自调用从新下载
        try:
            response = requests.get(url=url, timeout=120, headers=headers)
            with open(filename, 'ab+') as f:
                data = aes_decode(response.content, key)
                f.write(data)
                f.close()
        except Exception as ex:
            # print(ex.args, url)
            return self.auto_down(url, filename, headers, key)

    def threads(self):
        for i in range(len(self.ts_parts)):
            files = self.down_path + '/' + 'tsm{:0>5}.ts'.format(i)
            if os.path.exists(files):  # 判断文件是已下载,且文件大小变为空。是则结束本次循环,继续循环
                sz = os.path.getsize(files)
                if not sz:
                    os.remove(files)  # 删除空文件
                    print("删除空字节视频文件", files.rsplit("/", 1)[-1])
                else:
                    continue
            t = threading.Thread(target=self.load_ts, args=(self.ts_parts[i], files, i))
            self.tsthreads.append(t)

def main():  # This is m3u8 url
    url = 'https://www.XXXXX.com/20200612/jDCLCWyb/1500kb/hls/index.m3u8'

    hd = [('User-Agent', 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1941.0 Safari/537.36')]
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36",
        "Accept-Encoding": "gzip, deflate, br", "Connection": "keep-alive",
        "Accept-Language": "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2"} 

    m3u8 = m3u8down(url, hd, headers)
    m3u8.to_ts()
    m3u8.threads()

    for th in m3u8.tsthreads:
        th.start()

    for th in m3u8.tsthreads:
        th.join()

    print("{:-^20}".format("下载结束"))

if __name__ == '__main__':
    main()
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/161206.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 2015阿里校招前端在线题目[通俗易懂]

    2015阿里校招前端在线题目

    2022年1月27日
    43
  • 递归算法php,php递归算法经典实例「建议收藏」

    递归算法php,php递归算法经典实例「建议收藏」PHP递归算法就是函数调用函数了操作非常的简单了,我们下面来给各位介绍PHP递归算法及实际的一些关于递归的用法。递归函数为自调用函数,在函数体内直接或间接自己调用自己,但需要设置自调用的条件,若满足条件,则调用函数本身,若不满足则终止本函数的自调用,然后把目前流程的主控权交回给上一层函数来执行,可能这样给大家讲解,还是很难明白,直接上例子functiontest($n){echo$n.”…

    2022年8月11日
    6
  • Python暴力激活成功教程wifi密码

    Python暴力激活成功教程wifi密码今天给大家分享一个使用Python激活成功教程WiFi密码的代码,这个代码也是非常简单,这里需要用Python中的pywifi这个库,所以需要在DOS命令下安装这个库,同样使用pipinstallpywifi,很简单就安装成功了,我用的是Python3,所以各位看的时候需要注意这一点。接下来我们一步一步分析主要代码,后面同样附上完整的代码。对了,需要注意一点,就是电脑必须是要用无线网卡的。首先我们…

    2022年8月22日
    3
  • web 打印控件_JS插件

    web 打印控件_JS插件 平常浏览网页和文档的时候,随处可见打印两个字,有时候不小心点到,就会弹出一个打印的页面,如果连接了打印机,可以直接调用到打印机进行真实的打印。做为开发人员我们在网页开发过程中经常会有打印页面的需求,目前我正在做浏览器端采用JS方式实现打印这么一个功能,通过JS来实现的方法有很多,这里我分享一下我自已采用的方法,供大家参考。为了节约开发时间,我采用的是第三方打印软件“老牌打印控件WebPrinter”。新版现在已更名为“智睦云打印”,在原来的基础上增加了云打印机的支持,“智睦云打印”可以应用在本..

    2022年10月29日
    0
  • sort用的什么排序算法_lambda表达式有什么组成

    sort用的什么排序算法_lambda表达式有什么组成sort()与拉姆达表达式的结合#include<iostream>#include<string>#include<vector>#include<ctime>#include<map>#include<utility>#include<algorithm>usingstd::…

    2022年9月19日
    0
  • 最近招聘和面试的感想

    ​ 本篇博文写给自己,也写给那些在找工作或者找实习工作的伙伴。我的故事​ 刚刚入职新公司一个多月了,刚好前段时间有幸和公司的HR同事一起去湖南大学做公司的校招,湖大之前还是去过几次,只是之前去都是爬岳麓山,下山的时候路过。也没有怎么在湖大校园里面逛逛。这次是去校招,说真的,自己心里还挺激动。我毕业也有三年了,能回到大学校园里,那种感觉还是挺美好的。​ 校园招聘我也经历过,那个时候每天做车跑到…

    2022年2月27日
    36

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号