Python | 02.下载视频(普通视频、m3u8加密视频ts)

0.项目名字:getMovies

仅做技术分享使用,如侵必删

1.获取下载链接

以某网站的视频为例(不同网站的规则不同,这是其中一种未加密的)

F12进入开发者模式,在Network中找到mp4文件(可以从Media中筛选)

image-20210516135124609

Request URL对应的就是视频下载地址,也可以用下载器直接下载

2.下载准备

2.1.获取请求头

必须要有完整的请求头信息,否则要么无法访问URL,要么视频无法正确解码

image-20210516135410568

像这个是不可用的。

此时可以尝试将下载链接复制到浏览器地址栏去重新打开

便可获得完整的请求头信息

image-20210516135547304

附上自用的工具类源码,可将复制粘贴的请求头信息保存为字典类型

# -*- coding = utf-8 -*-
# @Time : 2021/5/11 16:50
# @Author : xyx-Eshang
# @File : headersUtil.py
# @software : PyCharm

import re


# 根据文本内容,获得headers
def getHeaders(headersStr):
    headers = {}
    headersList = re.findall(r':?(.*?): (.*)\n?', headersStr)
    for headersTuple in headersList:
        headers[headersTuple[0]] = headersTuple[1]
    return headers

image-20210516141749262

2.2.获取文件名

image-20210516140022512

文件名在下载链接中可以看到,这里使用正则表达式将文件名从url中提取出来

image-20210516140344211

2.3.创建好保存目录

保存路径对应的目录必须被提前创建好

如果路径不存在,直接用open()去调用是会报错的。

image-20210516140659950

强调下面两个函数:

import os

os.mkdir("路径")										# 创建文件夹
os.makedirs("路径")							 	# 创建包括父级文件夹在内的各级文件夹

1) os.mkdir()按照参数去创建文件夹,但如果中间某一父级文件夹不存在,就会报错。以下方为例

os.mkdir("../abc/def")		# 根据相对路径"../abc/def"创建def文件夹

如果…/abc这个文件夹存在,那么程序就可以正常执行;

但如果…/abc文件夹不存在,此时程序就会报错

2) os.makedirs()按照参数去逐级创建文件夹,能有效避免上述可能出现的错误,如果某一父级文件夹不存在,会一并创建。

3.下载文件

一切准备就绪以后,开始编写download()函数,需要的参数分别是

1) url

2) headers:请求头信息

3) full_file_name:完整的文件名

4) download_path:文件保存路径

image-20210516142718944

open()的模式必须用bytes模式,

覆盖写入用"wb",追加写入(视频拼接)用"ab"

附源代码

def download(url, headers, full_file_name, download_path):
    request = urllib.request.Request(url=url, method="GET", headers=headers)
    print("正在下载:" + full_file_name, end="...")
    try:
        response = urllib.request.urlopen(request)

        # 更换操作路径
        os.chdir(download_path)

        # 将下载的文件从内存拷贝到本地磁盘
        file = open(full_file_name, "wb")
        file.write(response.read())
        file.close()
        print("下载完成!")
    except urllib.error.HTTPError as e:
        if e.code == 404:
            print("该文件不存在!")
        else:
            print(e)

4.进阶练习:m3u8加密视频的下载

有的网站上传的视频是经过m3u8加密处理过的

这类视频的特点是:

完整的视频会被切割成很多个扩展名为.ts的小片段

如下图所示,F12进入开发者工具,在XHR中筛选

image-20210516143534894

由之前的内容可以得知,Request URL的内容就是这个视频片段的下载地址

而下载地址又和命名有关,仔细观察不难发现,文件的命名规则都是:

xxxxxxxx000.ts

xxxxxxxx001.ts

xxxxxxxx002.ts

有这样的规律就好办了,遍历下载所有的ts文件即可

这里针对核心部分,书写大致思路

4.1.遍历获得urlList列表和fullFileNameList列表

观察得知,一个视频的所有ts文件,url前面部分都是一样的

唯一的区别是后面的数字000、001、002…(或是00、01、02…)

因此可以用While True循环获取:

1) urlList:保存了所有的url

2) fullFileNameList:保存了所有的文件名(包括扩展名)

# 比如一共有3个ts文件,url分别是
# https://abcdefg01.ts
# https://abcdefg02.ts
# https://abcdefg03.ts

urlList = []												 # 保存所有的url
fullFileNameList = []								 # 保存所有的完整文件名
count = 0													  # 计数器
baseUrl = "https://abcdefg"						# url前面完全一致的部分
while True:
    try:
    		# 处理fullFileName
    		# 由于数字是01、02、03,这里需要手动拼接
    		if(count < 10):
        	fullFileName == "0" + str(count) + ".ts"
    		else:
        	fullFileName == str(count) + ".ts"
    		# 保存到列表中
    		fullFileNameList.append(fullFileName)
    
    		# 处理url
    		url = baseUrl + fullFileName
    		# 保存到列表中
    		urlList.append(url)
        
    except urllib.error.HTTPError as e:
        # 报404时,说明已经遍历完毕,终止循环
        if e.code == 404:
            break
        else:
            print(e)

4.2.循环访问url并下载

循环访问urlList的元素即可

保存的文件名则是fullFileNameList的元素

整体和上面思路几乎一直,只是在外层嵌套了循环

详细说明将耗费大量篇幅,因此这里留给大家独立完成

4.3.合并文件

在下载好所有的ts文件以后,便可以将这些文件合并起来

特别注意

在前面命名的时候,一定要把前面的"0"给加上,否则视频将不会按照期望的顺序去执行合并!

4.3.1.使用cmd指令合并

copy /b 原视频路径.* 新视频路径\合并文件名

比如这里希望将D:\Python下的所有ts文件,合并成combinedFile.mp4

那么指令就是

copy /b D:\Python.* D:\Python\combinedFile.mp4

4.3.2.使用python的文件写入来实现

image-20210516153147465

附源代码

def combineFiles(combinedFileName, downloadPath):
    # 更换操作目录
    os.chdir(downloadPath)
    try:
        # 若原有文件,则先移除文件
        os.remove(combinedFileName)
    except FileNotFoundError:
        # 若原来没有该文件,不做任何操作
        pass
    # 获取所有文件名
    allTsFileNames = os.listdir()
    for tsFileName in allTsFileNames:
        tsFile = open(tsFileName, "rb")
        combinedFile = open(combinedFileName, "ab")
        # 向目标文件追加内容
        combinedFile.write(tsFile.read())
        tsFile.close()
        # 删除ts文件
        os.remove(tsFileName)
    print("合并完成")
    os.chdir(defaultPath)

其中defaultPath是文件的默认操作路径,已在外层定义好

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值