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多进程编程下线程之间变量的共享问题
May 05 Python
python清除指定目录内所有文件中script的方法
Jun 30 Python
python3实现读取chrome浏览器cookie
Jun 19 Python
OpenCV-Python实现轮廓检测实例分析
Jan 05 Python
python实现聊天小程序
Mar 13 Python
python3获取当前文件的上一级目录实例
Apr 26 Python
Python根据文件名批量转移图片的方法
Oct 21 Python
python实现根据文件格式分类
Oct 31 Python
如何利用python web框架做文件流下载的实现示例
Jun 02 Python
Python bisect模块原理及常见实例
Jun 17 Python
python跨文件使用全局变量的实现
Nov 17 Python
python数字类型和占位符详情
Mar 13 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替换超长文本中的特殊字符的函数代码
2012/05/22 PHP
php+Memcached实现简单留言板功能示例
2017/02/15 PHP
关于PHP转换超过2038年日期出错的问题解决
2017/06/28 PHP
用YUI做了个标签浏览效果
2007/02/20 Javascript
javascritp实现input输入框相关限制用法
2007/06/29 Javascript
用Jquery实现滚动新闻
2014/02/12 Javascript
JavaSript中变量的作用域闭包的深入理解
2014/05/12 Javascript
node.js中的fs.realpathSync方法使用说明
2014/12/16 Javascript
项目中常用的JS方法整理
2015/01/30 Javascript
浅谈Javascript数组的使用
2015/07/29 Javascript
jquery简单实现网页层的展开与收缩效果
2015/08/07 Javascript
JS实现浏览器状态栏文字闪烁效果的方法
2015/10/27 Javascript
Jquery+Ajax+PHP+MySQL实现分类列表管理(下)
2015/10/28 Javascript
JS中sort函数排序用法实例分析
2016/06/16 Javascript
JavaScript中的await/async的作用和用法
2016/10/31 Javascript
VUE+Element环境搭建与安装的方法步骤
2019/01/24 Javascript
JavaScript和TypeScript中的void的具体使用
2019/09/12 Javascript
JS实现时间校验的代码
2020/05/25 Javascript
[42:50]NB vs VP 2018国际邀请赛小组赛BO2 第二场 8.18
2018/08/19 DOTA
使用wxPython获取系统剪贴板中的数据的教程
2015/05/06 Python
如何在sae中设置django,让sae的工作环境跟本地python环境一致
2017/11/21 Python
利用python计算windows全盘文件md5值的脚本
2019/07/27 Python
django创建最简单HTML页面跳转方法
2019/08/16 Python
用sqlalchemy构建Django连接池的实例
2019/08/29 Python
解决 jupyter notebook 回车换两行问题
2020/04/15 Python
快速解释如何使用pandas的inplace参数的使用
2020/07/23 Python
利用Python实现Json序列化库的方法步骤
2020/09/09 Python
Python中Yield的基本用法
2020/10/18 Python
使用css3实现超炫的loading加载动画效果
2014/05/07 HTML / CSS
什么是继承
2013/12/07 面试题
留学生求职信
2014/06/03 职场文书
2015年行政人事部工作总结
2015/05/13 职场文书
2016学校先进集体事迹材料
2016/02/29 职场文书
MySQL大小写敏感的注意事项
2021/05/24 MySQL
Go语言设计模式之结构型模式
2021/06/22 Golang
十大最强岩石系宝可梦,怪颚龙实力最强,第七破坏力很强
2022/03/18 日漫