'''
实现步骤
1,获得m3u8数据包。
2.解析m3u8数据包,获得对应的.ts地址。
3.向ts链接发送请求,获得小长度的视频
4,将视频拼接到一个.mp4.文件中
'''
# 导入需要的包,包括 json,threading,requests,re os
# 下载requests库:pip installer requests
import json
import threading
import requests
import re
import os
import time
# 腾讯视频 m3u8网址
url = "https://vd6.l.qq.com/proxyhttp"
# 定制请求头
headers = {
'Accept': '*/*',
'Accept-Encoding': 'gzip, deflate, br',
'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6',
'Connection': 'keep-alive',
'Content-Length': '3004',
'Content-Type': 'text/plain;charset=UTF-8',
'Cookie': 'RK=QIEMqoGwng; ptcz=810bf01bb62a13ab0dec5d3053b052e23f9c4f2dd59351690542f9aa9b75aadd; pgv_pvid=7079498850; tvfe_boss_uuid=eeba3896ea7f4b3a; o_minduid=2RTcYt6BwqUt32dSU8NQXrwmtJi_qz3h; appuser=A74E9FBD9657B4B2; [email protected]; uid=981297687; LCZCturn=811; LZTturn=513; LPDFturn=406; Lturn=630; LKBturn=132; pgv_info=ssid=s6042166256; _qpsvr_localtk=0.8303957016080734; vversion_name=8.2.95; video_omgid=94cc20951524fc84; LPVLturn=814; LPLFturn=406; LPSJturn=13; LVINturn=731; LPHLSturn=246; LDERturn=853; LPPBturn=418',
'Host': 'vd6.l.qq.com',
'Origin': 'https://v.qq.com',
'Referer': 'https://v.qq.com/',
'sec-ch-ua': '"Chromium";v="110", "Not A(Brand";v="24", "Microsoft Edge";v="110"',
'sec-ch-ua-mobile': '?0',
'sec-ch-ua-platform': '"Windows"',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'same-site',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36 Edg/110.0.1587.63',
}
# 定制请求参数
json_1 = input("请输入请求数据")
json_1 = json.loads(json_1)
# 发起请求,使用post请求 post请求需要请求参数 python3.9取消了date写法,需以字典的形式,传值给json
response = requests.post(url=url, headers=headers, json=json_1)
text = response.json()
# 解析json格式
text = text["vinfo"]
# 字典取值,得到字符串
# ["vi"][0]["ul"]["m3u8"]
json_date = json.loads(text)["vl"]["vi"][0]["ul"]["m3u8"] # 将字符串转为json格式
json_date = re.sub('#EXT.*', '', json_date) # 用正则表达式,取出ts文件的短地址
m3u8_list = json_date.split()
headers1 = {
'Accept': '*/*',
'Accept-Encoding': 'gzip, deflate, br',
'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6',
'Connection': 'keep-alive',
'Host': 'apd-8245a32de713f4ba8d9280f1af28220108632f5a868c5ce6.v.smtcdns.com',
'Origin': 'https://v.qq.com',
'Referer': 'https://v.qq.com/',
'sec-ch-ua': '"Chromium";v="110", "Not A(Brand";v="24", "Microsoft Edge";v="110"',
'sec-ch-ua-mobile': '?0',
'sec-ch-ua-platform': '"Windows"',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36 Edg/110.0.1587.63',
}
def downlond(m3u8_list, headers1, num, url_star):
'''
此函数用来执行爬取视频操作,。
:param m3u8_list: 分割后的m3u8列表
:param headers1: 请求头
:param num: 文件名的控制参数
:param url_star: 爬取腾讯视频的链接请求头
:return: 无返回值
'''
for i in m3u8_list:
url = url_star + i
video = requests.get(url=url, headers=headers1)
with open(f'test{num}.mp4', 'ab') as f:
f.write(video.content)
if __name__ == '__main__':
l = []
url_star = input('请输入链接头') # 需要将获得的短链接与链接头拼接,请求输入链接头
a = time.time()
'''
将列表拆分成4个列表
用列表推到式,将分割后的列表追加到一个新列表中
'''
size = len(m3u8_list) // 4
new_m3u8_list = [m3u8_list[i:i + size] for i in range(0, len(m3u8_list), size)]
for i in range(4):
'''
启动四个线程,让其分别执行下载功能,加快下载速度
'''
t = threading.Thread(target=downlond, args=(new_m3u8_list[i], headers1, i, url_star))
t.start()
l.append(t)
for p in l:
p.join()
for i in range(4):
'''
将多线程下载的数据多个文件合并到一个文件中
'''
chr_num = str(i)
with open(f'test{chr_num}.mp4', mode='rb') as f:
video_date = f.read()
with open('move2.mp4', mode='ab') as f1:
f1.write(video_date)
'''
调用时间模块
统计运行时间
'''
for i in range(4):
'''
删除多线程下载的小视频
'''
os.remove(f'test{i}.mp4')
b = time.time()
print(a - b)