python代码下载m3u8视频

代码如下:

# -*- coding: utf-8 -*-
import requests
import re
import os
import base64
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
BLOCK_SIZE = 16  # Byte


def write_file(file_path, content, attr):
	"""
	写内容进文件
	:param file_path:
	:param content:
	:param attr:
	:return:
	"""
	with open(file_path, attr) as f:
		f.write(content)


def get_urls(m3u8_url):
	"""
	获取视频url
	:param m3u8_url:
	:return:
	"""
	# 分割url为文件和路径
	remote_path, file_name = os.path.split(m3u8_url)
	urls = []
	try:
		res = requests.get(url=m3u8_url)
		url_regs = re.findall('#EXTINF:(.*?),\n(.*?)\n', res.text)  # 正则提取url

		for url_reg in url_regs:
			# 判断是否完整url
			if 'http' not in url_reg[1]:
				url = remote_path + "/" + url_reg[1]
				urls.append(url)
				# print(url)
			else:
				urls.append(url_reg[1])
		print('【url获取完成】')
	except Exception as e:
		print(e)
		print('【url获取失败】')
	return urls


def get_key(m3u8_url):
	"""
	获取解密密钥
	:param m3u8_url:
	:return:
	"""
	# 分割url为文件和路径
	remote_path, file_name = os.path.split(m3u8_url)
	key = None
	try:
		res = requests.get(url=m3u8_url)
		key_regs = re.findall('#EXT-X-KEY:METHOD=(.*?),URI="(.*?)"', res.text) # 正则提取解密密钥
		# 判断是否完整url
		if 'http' not in key_regs[0][1]:
			key_url = remote_path + '/' + key_regs[0][1]
		else:
			key_url = key_regs[0][1]
		# 请求key
		key = requests.get(url=key_url).content
		print('【密钥获取完成】')
	except Exception as e:
		print(e)
		print('【密钥获取失败】')
	return key


def download_video(m3u8_url, file_name):
	"""
	下载视频
	:param m3u8_url:
	:param file_name:
	:return:
	"""
	# 记录已下载的数据大小,单位Byte
	total = 0
	try:
		# 获取解密密钥
		key = get_key(m3u8_url)
		# 获取url
		urls = get_urls(m3u8_url)
		# 循环下载每个部分的视频
		for url in urls:
			print('【正在下载 '+url+' 部分的视频】')
			res = requests.get(url=url)
			# 解密
			content = aes_decrypt(key, res.content)
			total += len(content)
			# 追加进文件
			write_file(file_name, content, 'ab+')
			print('【下载完成 ' + url + ' 部分的视频】')
			print('【已下载部分大小:'+str(total/1024)+' kb/'+str(total/(1024*1024))+' mb】')
		print('【下载完成】')
	except Exception as e:
		print(e)


def aes_decrypt(key, crypt_content):
	"""
	解密
	:param key:
	:param crypt_content:
	:return:
	"""
	cryptor = AES.new(key, AES.MODE_CBC, key)
	pad_content = pad(crypt_content, BLOCK_SIZE)
	# print(len(crypt_content))
	return unpad(cryptor.decrypt(crypt_content), BLOCK_SIZE)
	# return cryptor.decrypt(crypt_content)


def aes_encrypt(key, text):
	"""
	加密
	:param key:
	:param text:
	:return:
	"""
	cryptor = AES.new(key, AES.MODE_CBC, key)
	return cryptor.encrypt(pad(text.encode(), BLOCK_SIZE))
	# return cryptor.encrypt(text.encode())


def main():
	download_video('http://1252524126.vod2.myqcloud.com/9764a7a5vodtransgzp1252524126/69f662df5285890816956396169/drm/v.f146750.m3u8', 'test.mp4')
	# print(get_key('https://1252524126.vod2.myqcloud.com/9764a7a5vodtransgzp1252524126/430c15b95285890816864188760/drm/v.f146750.m3u8'))

if __name__ == '__main__':
	main()

 

posted @ 2021-04-15 17:37  SirPi  阅读(562)  评论(0编辑  收藏  举报