首先
我爬取的是茶杯狐网站的视频,视频为m3u8格式,需要下载多个小片段最后再进行拼接。
网址为
茶杯狐 cupfox官网-最新电影电视剧免费在线观看 (shjhbox.com)https://www.shjhbox.com/
因为拼接过程中需要使用到ffmpeg软件,所以要在系统中进行环境变量的配置,具体参考如下
需要注意的是,配置完成后,应在命令行中输入ffmpeg -version命令检测是否配置成功,有些电脑的python编译器可能无法立即检测到环境变量是否配置,重启之后即可解决。
配置完成如下
接下来是Python代码
import os
import re
import threading
import time
from concurrent.futures import ThreadPoolExecutor, wait
import requests
# 定义全局变量,记录ts文件下载数
num = 0
headers = {
"User-Agent":
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36"
}
# 电影名称
name = ''
def get_m3u8_list(url):
global name
session = requests.Session()
# 获取网页内容
resp = session.get(url, headers=headers).text
# 获取标题
name = re.findall("var vod_name = '(.*?)'", resp)[0].replace(' ', '')
# 获取第一个m3u8的内容
first_m3u8_url = re.findall('"link_pre":"","url":"(.+?index.m3u8)"', resp)[0].replace('\\', '')
first_m3u8 = session.get(first_m3u8_url, headers=headers)
# 获取第二个m3u8的内容
if 'http' in first_m3u8.text:
second_m3u8_url = re.findall('(http.*?m3u8)', first_m3u8.text)[0]
else:
second_m3u8_url = 'https:' + '//' + first_m3u8_url.split('/')[2] + '/' + \
re.findall('/(.*?m3u8)', first_m3u8.text)[
0]
second_m3u8 = session.get(second_m3u8_url, headers=headers)
m3u8_url_list = re.findall('(htt.*?ts)', second_m3u8.text)
return m3u8_url_list
# 下载单个ts文件
def download_one_m3u8(m3u8_url, path, i):
global num
m3u8 = requests.get(m3u8_url, headers=headers)
print(i, '开始下载')
with open(path + f'/{i}.ts', mode='wb') as f:
f.write(m3u8.content)
print(i, '下载完成')
# 每下载一个文件,数量加1
num += 1
# 下载全部ts文件
def download_all_m3u8(lists):
path = './' + name
if not os.path.exists(path):
os.mkdir(path)
# 创建线程池
pool = ThreadPoolExecutor(200)
i = 0
tasks = []
for item in lists:
tasks.append(pool.submit(download_one_m3u8, item, path, i))
i += 1
# 等待下载完毕
wait(tasks)
merge(path)
def merge(filePath, filename='output'):
'''
进行ts文件合并 解决视频音频不同步的问题 建议使用这种
:param filePath:
:return:
'''
# 根据当前文件名称的数字进行排序
file_list = sorted(os.listdir(filePath), key=lambda x: int(x.split('.')[0]))
length = len(file_list)
# ./ts/1.ts|./ts/2.ts ...
# ffmpeg 无法一次拼接过多文件,应分开拼接,最后合并
for i in range(int(length / 100) + 1):
Str = ''
# 一次拼接100个
for j in range(i * 100, (i + 1) * 100):
if j == length:
break
Str += f'{filePath}/' + file_list[j] + '|'
cmd = f'ffmpeg -i "concat:{Str}" -c copy "{name + str(i)}.ts"'
print(os.system(cmd))
mp4 = ''
# 拼接最终的文件
for i in range(int(length / 100) + 1):
mp4 += f'./{name + str(i)}.ts|'
cmd = f'ffmpeg -i "concat:{mp4}" -c copy "./电影/{name}.mp4"'
print(os.system(cmd))
# 删除中间过程中产生的ts文件
for i in range(int(length / 100) + 1):
remove = f'del {name + str(i)}.ts'
os.system(remove)
# 删除所有ts文件
os.system(f'rd {name} /s /q ')
merge(f'./{name}')
# 定时执行结束函数,强制程序退出
def jieshu():
global num
# 循环检查当前是否在下载文件,如果超出30秒未下载文件,则停止下载,并将已下载的文件拼接完整
while 1:
num1 = num
print('已下载', num)
time.sleep(30)
if num1 == num:
merge(f'./{name}')
print('下载结束')
os.system("taskkill /f /t /im python.exe")
if __name__ == '__main__':
url = input('请输入url')
print('开始下载')
# url = 'https://www.shjhbox.com/vodplay/66776-1-1.html'
# 创建文件夹
if not os.path.exists('./电影'):
os.mkdir('./电影')
# 获取下载文件目录
m3u8_url_list = get_m3u8_list(url)
# 开始计时
threading.Thread(target=jieshu).start()
print('over')
# 开始下载
download_all_m3u8(m3u8_url_list)
有些软件包可能需要自己下载,如果无法下载的话建议使用阿里的源进行下载。
效果展示
而且,这个网站可能会比较卡,所以建议线程开的少一点,代码中同时开了100个线程,
并且设置了如果30秒没有下载任何文件,则直接停止下载,并将已下载好的视频拼接完成,
也可以适当延长时间
url的输入格式为播放页的地址,如下