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 相关文章推荐
关于反爬虫的一些简单总结
Dec 13 Python
Python基于FTP模块实现ftp文件上传操作示例
Apr 23 Python
pandas DataFrame 根据多列的值做判断,生成新的列值实例
May 18 Python
Python3实现的Mysql数据库操作封装类
Jun 06 Python
Python+selenium 获取一组元素属性值的实例
Jun 22 Python
Python实现的各种常见分布算法示例
Dec 13 Python
Python标准库使用OrderedDict类的实例讲解
Feb 14 Python
华为校园招聘上机笔试题 扑克牌大小(python)
Apr 22 Python
python time.sleep()是睡眠线程还是进程
Jul 09 Python
完美解决python3.7 pip升级 拒绝访问问题
Jul 12 Python
virtualenv介绍及简明教程
Jun 23 Python
Django启动时找不到mysqlclient问题解决方案
Nov 11 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/03/12 PHP
分享10篇优秀的jQuery幻灯片制作教程及应用案例
2011/04/16 Javascript
JavaScript判断变量是对象还是数组的方法
2014/08/28 Javascript
PhotoShop给图片自动添加边框及EXIF信息的JS脚本
2015/02/15 Javascript
JS随机调用指定函数的方法
2015/07/01 Javascript
bootstrap导航条实现代码
2016/12/28 Javascript
Ajax验证用户名或昵称是否已被注册
2017/04/05 Javascript
angular中使用Socket.io实例代码
2017/06/03 Javascript
AngularJs导出数据到Excel的示例代码
2017/08/11 Javascript
Vue Transition实现类原生组件跳转过渡动画的示例
2017/08/19 Javascript
微信小程序switch组件使用详解
2018/01/31 Javascript
JavaScript闭包原理与用法实例分析
2018/08/10 Javascript
利用JS响应式修改vue实现页面的input值
2019/09/02 Javascript
微信小程序 点击切换样式scroll-view实现代码实例
2019/10/11 Javascript
稍微学一下Vue的数据响应式(Vue2及Vue3区别)
2019/11/21 Javascript
Python中文竖排显示的方法
2015/07/28 Python
Python 加密的实例详解
2017/10/09 Python
Python实现的选择排序算法示例
2017/11/29 Python
详解Python在七牛云平台的应用(一)
2017/12/05 Python
python http接口自动化脚本详解
2018/01/02 Python
Python打印输出数组中全部元素
2018/03/13 Python
Window10上Tensorflow的安装(CPU和GPU版本)
2020/12/15 Python
使用CSS3实现字体颜色渐变的实现
2020/08/10 HTML / CSS
马来西亚航空官方网站:Malaysia Airlines
2017/07/28 全球购物
以色列的身体护理及家居香薰品牌:Sabon NYC
2018/02/23 全球购物
德国户外商店:eXXpozed
2020/07/25 全球购物
电气工程师岗位职责
2014/01/01 职场文书
活动倡议书范文
2014/05/13 职场文书
民生工作实施方案
2014/05/31 职场文书
建筑安全生产责任书
2014/07/22 职场文书
2014年检验员工作总结
2014/11/19 职场文书
学术研讨会欢迎词
2015/01/26 职场文书
病危通知书样本
2015/04/17 职场文书
同意落户证明
2015/06/19 职场文书
2019西餐厅创业计划书范文!
2019/07/12 职场文书
MySQL实现用逗号进行拼接、以逗号进行分割
2022/12/24 MySQL