赞
踩
首先
我爬取的是茶杯狐网站的视频,视频为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的输入格式为播放页的地址,如下
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。