m3u8视频下载器

文章目录

  • 前言
  • 一、获取网站的m3u8文件url
  • 二、使用步骤
    • 1.修改配置文件
    • 2.运行py或者exe
  • 总结


前言

有的时候看个视频太卡了,就想把视频搞下来,一些网站吧,它不让下载,而且还是ts流视频,于是就做了个m3u8视频下载器第一版本,如果大家使用的时候有问题,欢迎在评论区留言哦。


一、获取网站的m3u8文件url

打开想看的视频,然后F12打开控制台,找网络,里边搜索m3u8,然后刷新页面
m3u8视频下载器_第1张图片
将url复制出来,后续用。

二、使用步骤

1.修改配置文件

m3u8视频下载器_第2张图片

2.运行py或者exe

# -*- coding: utf-8 -*-
import os
import re
from concurrent.futures import ThreadPoolExecutor, as_completed
from configparser import ConfigParser
import requests
from Crypto.Cipher import AES
import subprocess

tPool = ThreadPoolExecutor(max_workers=30)
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36 Edg/106.0.1370.42',
    'Connection': 'close'
}
cryptor = None
tasks = []


def build_mk_ts():
    mk_ts_path = os.getcwd() + r'\ts'
    if not os.path.exists(mk_ts_path):
        os.mkdir(mk_ts_path)


def set_file_name(file_name):
    illegal_char = ['\\', '/', ':', '*', '?', '"', '<', '>', '|']
    for char in illegal_char:
        file_name = file_name.replace(char, '-')
    return file_name


def read_config():
    config = ConfigParser()
    config_path = os.getcwd() + r'\config.ini'
    config.read(config_path, encoding='utf-8')
    return config


def m3u8_down(m3u8_url):
    resp = requests.get(m3u8_url, headers=headers)
    resp.raise_for_status()
    m3u8_text = resp.text
    return m3u8_text


def url_merge(m3u8_url, url):
    m3u8_url_li = m3u8_url.split('/')
    url_li = url.split('/')
    for _ in url_li:
        if len(_) != 0:
            if _ in m3u8_url_li:
                index = m3u8_url_li.index(_)
                url_head = ('/').join(m3u8_url_li[:index])
            else:
                url_head = ('/').join(m3u8_url_li[:-1])
            break
    if url[0] == '/':
        return url_head + url
    else:
        if len(url_head) != 0:
            return url_head + '/' + url
        else:
            return url_head + url


def m3u8_analysis(m3u8_url, m3u8_text):
    global cryptor
    if "#EXT-X-KEY:METHOD=" in m3u8_text:
        key_url = re.findall('URI="(.*?)"', m3u8_text)[0]
        key_url = url_merge(m3u8_url, key_url)
        resp = requests.get(key_url, headers=headers)
        resp.raise_for_status()
        key = resp.content
        cryptor = AES.new(key, AES.MODE_CBC, key)
    ts_url_li = re.findall('#EXTINF.*?,\n(.*)', m3u8_text)
    return ts_url_li


def ts_down(index, ts_url, m3u8_url):
    ts_url = url_merge(m3u8_url, ts_url)
    resp = requests.get(ts_url, headers=headers, timeout=5)
    resp.raise_for_status()
    by = resp.content
    if cryptor:
        by = cryptor.decrypt(by)
    with open(f'{os.getcwd()}\\ts/{str(index).zfill(5)}.ts', 'wb') as f:
        f.write(by)


def ts_merge(mp4_name):
    mp4_name = set_file_name(mp4_name)
    if 'mp4' not in mp4_name.lower():
        mp4_name += '.mp4'

    cmd = rf'copy /b {os.getcwd()}\ts\*.ts {os.getcwd()}\ts\{mp4_name}'
    subprocess.run(cmd, shell=True)
    del_cmd = rf'del /Q {os.getcwd()}\ts\*.ts'
    subprocess.run(del_cmd, shell=True)


def run():
    try:
        build_mk_ts()
        config = read_config()
        m3u8_url = config.get('api', 'm3u8_url')
        m3u8_text = m3u8_down(m3u8_url)
        ts_url_li = m3u8_analysis(m3u8_url, m3u8_text)
        for index, ts_url in enumerate(ts_url_li):
            task = tPool.submit(ts_down, index, ts_url, m3u8_url)
            tasks.append(task)
        count = 0
        for _ in as_completed(tasks, timeout=60 * 2):
            count += 1
            print(f'\r爬取进度:{int(count / len(tasks) * 100)}%', end='')
        print('\n爬取完毕')

        ts_merge(config.get('api', 'mp4_name'))
        print('合并完成!')
    except Exception as e:
        print(e)
    finally:
        input('请手动关闭!')


if __name__ == '__main__':
    run()


总结

代码中用到的aes的解密,这个兼容了需要解密的和不需要解密的,都可以使用,想直接用exe和代码文件的私信领取哦。

你可能感兴趣的:(python)