python基于tkinter制作m3u8视频下载工具


Posted in Python onApril 24, 2021

这是我为了学习tkinter用python 写的一个下载m3u8视频的小程序,程序使用了多线程下载,下载后自动合并成一个视频文件,方便播放。

目前的众多视频都是m3u8的播放类型,只要知道视频的m3u8地址,就可以完美下载整个视频。

m3u8地址获取

打开浏览器,点开你要获取地址的视频

 python基于tkinter制作m3u8视频下载工具

重要的来了,右键>>审查元素或者按F12也可以

根据开发或测试的实际环境选择相应的设备,选择iphone6 plus

python基于tkinter制作m3u8视频下载工具

选择好了以后,刷新页面,点击漏斗,选择media,一定刷新之后再点击,没出来的话切换几下选项卡,就能出来了

python基于tkinter制作m3u8视频下载工具

点击播放视频,在下边就可以看到地址了

python基于tkinter制作m3u8视频下载工具

程序代码

# -*- coding: UTF-8 -*-
import sys

sys.path.append("C:\\Python36-32\\Lib\\site-packages")
import tkinter
import re
import urllib3
import threadpool
import threading
import os
import shutil
import time
import glob
from tkinter.ttk import *
from PIL import Image, ImageTk
import pyperclip
from tkinter.filedialog import askdirectory

def get_image(filename,width,height):
    im = Image.open(filename).resize((width,height))
    return ImageTk.PhotoImage(im)


def get_resource_path(relative_path):
    if hasattr(sys, '_MEIPASS'):
        return os.path.join(sys._MEIPASS, relative_path)
    return os.path.join(os.path.abspath("."), relative_path)


def getrealtask(link):
    global key
    rooturl1 = ''
    rooturl2 = ''
    pattern3 = re.compile(r'^.*[\/]', re.M)
    result11 = pattern3.findall(link)
    if result11:
        rooturl1 = result11[0]
    pattern4 = re.compile(r'^http[s]?:\/\/[^\/]*', re.M)
    result114 = pattern4.findall(link)
    if result114:
        rooturl2 = result114[0]
    res = http.request('GET', link)
    content = str(res.data, 'utf8')
    list = content.split('\n')
    reallist = []
    for one in list:
        if one.endswith('"key.key"'):
            keyurl = rooturl1 + "key.key"
            res = http.request('GET', keyurl)
            key = str(res.data, 'utf8')
        if one.endswith('.ts') or one.endswith('.image'):
            if re.match(r'http', one, re.M | re.I):
                reallist.append(one)
            elif re.match(r'\/', one, re.M | re.I):
                reallist.append(rooturl2 + one)
            else:
                reallist.append(rooturl1 + one)
        if one.endswith('.m3u8'):
            if re.match(r'\/', one, re.M | re.I):
                reallist = getrealtask(rooturl2 + one)
            else:
                reallist = getrealtask(rooturl1 + one)
            break
    return reallist

def download_ts(result):
    url = result['url']
    name = result['name']
    num = result['num']
    rootpath = result['root']
    m3u8Name = result['m3u8name']
    t= str(result['total'])
    if num % 10000 == 0:
        print(str(num)+' / '+t)
    basepath = os.path.join(rootpath,m3u8Name)
    fullpath = os.path.join(basepath,name)
    isExist = os.path.exists(fullpath)
    if not isExist:
        http = urllib3.PoolManager(timeout=10.0)
        while(1):
            try:
                f = http.request('GET', url)
                break
            except:
                print("URL ERRO: " + url)
                time.sleep(2)
        d = f.data
        with open(fullpath, "wb") as code:
            code.write(d)
        print("SAVE: " + url)
def clock2(num,path):
    global window
    global key
    v3 = tkinter.StringVar();
    v4 = tkinter.StringVar();
    l3 = tkinter.Label(window, text='', textvariable=v3, font=('Arial', 10))
    l4 = tkinter.Label(window, text='', textvariable=v4, font=('Arial', 10))
    l3.place(x=10, y=130, anchor='nw')
    l4.place(x=10, y=160, anchor='nw')
    v3.set("下载中。。。")
    while(1):
        path_file_number = len(glob.glob(path+'/*.ts'))
        mp4_file_number = len(glob.glob(path + '/*.mp4'))
        numberstr = str(path_file_number) + '/'+str(num)
        v4.set(numberstr)
        if mp4_file_number==1:
            v3.set("下载完成!")
            key = ''
            break

def clock1():
    global v
    global v2
    global rootpath
    m3u8Name = v2.get()
    url = v.get()
    print(url)
    urls = getrealtask(url)
    total = len(urls)
    i = 0
    tasks = []
    tsNames = []
    for one in urls:
        task = {}
        task['root'] = rootpath
        task['m3u8name'] = m3u8Name
        task['url'] = one
        task['num'] = i
        task['total'] = total
        task['name'] = str(i) + '.ts'
        tsNames.append(str(i) + '.ts')
        i = i + 1
        tasks.append(task)
    print('tasks: ' + str(len(tasks)))
    targetpath = os.path.join(rootpath, m3u8Name)
    if not os.path.exists(targetpath):
        os.makedirs(targetpath)
    timer2 = threading.Thread(target=clock2,args=(len(tasks),targetpath))
    timer2.daemon = True
    timer2.start()
    requests = threadpool.makeRequests(download_ts, tasks)
    [task_pool.putRequest(req) for req in requests]
    task_pool.wait()
    mp4targetfile = os.path.join(targetpath, m3u8Name + '.mp4')
    with open(mp4targetfile, 'wb') as f:
        for ts in tsNames:
            tstargetfile = os.path.join(targetpath, ts)
            with open(tstargetfile, 'rb') as mergefile:
                shutil.copyfileobj(mergefile, f)
            print(tstargetfile + ' merged.')
        for tts in tsNames:
            tstargetfile = os.path.join(targetpath, tts)
            os.remove(tstargetfile)
    print(total)

def hit_me():
    global on_hit
    timer = threading.Thread(target=clock1)
    timer.daemon = True
    timer.start()
    return

def choose_dir():
    global v5
    global rootpath
    rootpath = askdirectory()
    v5.set('文件夹: '+rootpath+'/')
    return

def about():
    window = tkinter.Toplevel()
    window.geometry('600x100')# Note Toplevel, NOT Tk.
    msg = 'Rax m3u8下载器 v1.4\n写这个程序主要是为了学习Tk,顺便满足下自己看视频的需求。\n家里的移动网络看在线视频还是有些卡顿的。 '
    label = tkinter.Label(window, text=msg,font=('Arial', 15))
    label.grid()
def update():
    window = tkinter.Toplevel()
    window.geometry('250x200')
    msg = 'Rax m3u8下载器 v1.5\n可以选择保存的目录了\nRax m3u8下载器 v1.4\n增加了菜单栏'
    label = tkinter.Label(window, text=msg,font=('Arial', 13))
    label.place(x=30, y=30, anchor='nw')
def donate():
    window = tkinter.Toplevel()
    window.geometry('500x400')
    msg = '软件免费使用\n欢迎喜欢此软件的各位大佬打赏,谢谢。'
    label = tkinter.Label(window, text=msg, font=('Arial', 20))


    i1 = tkinter.PhotoImage(file=get_resource_path("images\\wx.png"))
    i2 = tkinter.PhotoImage(file=get_resource_path("images\\zfb.png"))
    imagelabel = tkinter.Label(window, text='aaa', image=i1, font=('Arial', 10))
    imagelabel2 = tkinter.Label(window, text='vvv', image=i2, font=('Arial', 10))
    imagelabel.place(x=10, y=145, anchor='nw')
    imagelabel2.place(x=230, y=145, anchor='nw')
    label.place(x=40, y=50, anchor='nw')
    window.mainloop()
def clear():
    global v
    v.set("")
def paste():
    global v
    v.set(pyperclip.paste())

key = ''
on_hit = False
rootpath = "d:\\"
#最高50线程
task_pool = threadpool.ThreadPool(50)
http = urllib3.PoolManager(timeout=5.0)
urllib3.disable_warnings()

#主窗口初始化
window = tkinter.Tk()
window.style = Style()
window.style.theme_use("clam")
window.title("Rax m3u8视频下载器")
window.geometry('500x300')
window.resizable(0,0)


#飞机背景图
canvas_root = tkinter.Canvas(window,width=500,height=300)
im_root = get_image(get_resource_path('images\\feiji.jpeg'),500,300)
canvas_root.create_image(250,240,image=im_root)
canvas_root.pack()

#各控件初始状态
l1 = tkinter.Label(window, text='m3u8地址:', font=('Arial', 10))
l1.place(x=10, y=0, anchor='nw')

#   地址栏
v = tkinter.StringVar();
e2 = tkinter.Entry(window, show=None, textvariable = v,font=('Arial', 10),width=40)
v.set('')
e2.place(x=10, y=30, anchor='nw')

#   视频名称
l6 = tkinter.Label(window, text = ' 视频文件名称:', font=('Arial', 10))
l6.place(x=0, y=90, anchor='nw')

#   视频名称栏
v2 = tkinter.StringVar();
e3 = tkinter.Entry(window, show=None, textvariable = v2,font=('Arial', 10),width=15)
v2.set('')
e3.place(x=105, y=90, anchor='nw')

#   保存位置
v5 = tkinter.StringVar();
l2 = tkinter.Label(window, textvariable = v5, font=('Arial', 10))
v5.set('文件夹: D:/')
l2.place(x=10, y=60, anchor='nw')

#   下载按钮
b = tkinter.Button(window, text='下载', font=('Arial', 10), width=10, command=hit_me)
b.place(x=400, y=100, anchor='nw')

#   选择路径按钮
pathselectButton = tkinter.Button(window, text='选择路径', font=('Arial', 10), width=10, command=choose_dir)
pathselectButton.place(x=400, y=60, anchor='nw')

#   清空按钮
b2 = tkinter.Button(window, text='清空', font=('Arial', 10), width=10, command=clear)
b2.place(x=300, y=25, anchor='nw')

#   粘贴地址按钮
b3 = tkinter.Button(window, text='粘贴地址', font=('Arial', 10), width=10, command=paste)
b3.place(x=400, y=25, anchor='nw')

#   求捐赠按钮
l5 = tkinter.Label(window, text='软件免费使用,欢迎各位喜欢此软件的大佬打赏,谢谢。\nQQ讨论群:519565890', font=('Arial', 10))
l5.place(x=100, y=160, anchor='nw')

window.option_add('*tearOff', False)

#菜单栏
menubar = tkinter.Menu(window)
window['menu'] = menubar
help_menu = tkinter.Menu(menubar)
menubar.add_command(label='捐助作者',command=lambda: donate())
menubar.add_cascade(menu=help_menu, label='帮助')

#帮助 下拉菜单
help_menu.add_command(label='更新内容',command=lambda: update())
help_menu.add_command(label='关于',command=lambda: about())

# 进入消息循环
window.mainloop()

项目地址

https://github.com/raxar81/rax_m3u8_downloader

以上就是python基于tkinter制作m3u8视频下载工具的详细内容,更多关于python m3u8视频下载的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
举例详解Python中的split()函数的使用方法
Apr 07 Python
Python模拟登陆淘宝并统计淘宝消费情况的代码实例分享
Jul 04 Python
Python迭代和迭代器详解
Nov 10 Python
Python实现可设置持续运行时间、线程数及时间间隔的多线程异步post请求功能
Jan 11 Python
简单实现python聊天程序
Apr 01 Python
python环形单链表的约瑟夫问题详解
Sep 27 Python
用python建立两个Y轴的XY曲线图方法
Jul 08 Python
python列表,字典,元组简单用法示例
Jul 11 Python
pycharm新建一个python工程步骤
Jul 16 Python
tensorflow 环境变量设置方式
Feb 06 Python
Python安装OpenCV的示例代码
Mar 05 Python
python list的index()和find()的实现
Nov 16 Python
用python自动生成日历
解决Django transaction进行事务管理踩过的坑
Apr 24 #Python
pdf论文中python画的图Type 3 fonts字体不兼容的解决方案
Apr 24 #Python
Python使用UDP实现720p视频传输的操作
python通配符之glob模块的使用详解
Apr 24 #Python
Django debug为True时,css加载失败的解决方案
Apr 24 #Python
python 模块重载的五种方法
Apr 24 #Python
You might like
php将金额数字转化为中文大写
2015/07/09 PHP
PHP Cookei记录用户历史浏览信息的代码
2016/02/03 PHP
PHP常见错误提示含义解释(实用!值得收藏)
2016/04/25 PHP
php好代码风格的阶段性总结
2016/06/25 PHP
PHP创建XML接口示例
2019/07/04 PHP
laravel框架 api自定义全局异常处理方法
2019/10/11 PHP
用js+xml自动生成表格的东西
2006/12/21 Javascript
jquery xMarquee实现文字水平无缝滚动效果
2014/04/29 Javascript
在JavaScript中操作时间之getMonth()方法的使用
2015/06/10 Javascript
jQuery页面加载初始化的3种方法(推荐)
2016/06/02 Javascript
Javascript动画效果(3)
2016/10/11 Javascript
使用smartupload组件实现jsp+jdbc上传下载文件实例解析
2017/01/05 Javascript
ajax 提交数据到后台jsp页面及页面跳转问题
2017/01/19 Javascript
JavaScript数组迭代方法
2017/03/03 Javascript
jQuery实现百度登录框的动态切换效果
2017/04/21 jQuery
Node.js搭建小程序后台服务
2018/01/03 Javascript
基于nodejs的微信JS-SDK简单应用实现
2019/05/21 NodeJs
python pdb调试方法分享
2014/01/21 Python
python 遍历目录(包括子目录)下所有文件的实例
2018/07/11 Python
python opencv 读取图片 返回图片某像素点的b,g,r值的实现方法
2019/07/03 Python
从列表或字典创建Pandas的DataFrame对象的方法
2019/07/06 Python
python requests更换代理适用于IP频率限制的方法
2019/08/21 Python
Python多线程爬取豆瓣影评API接口
2019/10/22 Python
使用Python实现Wake On Lan远程开机功能
2020/01/22 Python
python如何实现单链表的反转
2020/02/10 Python
Python读写操作csv和excle文件代码实例
2020/03/16 Python
基于keras中的回调函数用法说明
2020/06/17 Python
canvas实现图片马赛克的示例代码
2018/03/26 HTML / CSS
使用HTML5加载音频和视频的实现代码
2020/11/30 HTML / CSS
人力资源经理自我评价
2014/01/04 职场文书
商场消防演习方案
2014/02/12 职场文书
有多年工作经验的自我评价
2014/03/02 职场文书
学校地质灾害防治方案
2014/06/10 职场文书
幼儿园园长新年寄语2015
2014/12/08 职场文书
导游词之杭州岳王庙
2019/11/13 职场文书
PHP面试题 wakeup魔法 Ezpop pop序列化与反序列化
2022/04/11 PHP