python网络请求:下载mp4文件并获取时长
python网络请求:下载mp4文件并获取时长
import json
import os
import random
import subprocess
import time
import requests
import urllib3
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
class CourseLearning:
def __init__(self, cookie, le_id):
self.website_action_main_url = 'https://*************/front/command/WebSiteAction'
self.lesson_action_main_url = 'https://*************/front/command/LessonAction'
self.mp4_main_url = 'https://media*************/resource//mp4Course'
self.mp4_save_dir = self.get_current_file_dir() + os.sep + 'mp4'
self.json_headers = {
'Content-Type': 'application/json;charset=UTF-8',
'Cookie': cookie
}
self.html_headers = {
'Content-Type': 'text/html;charset=utf-8',
'Cookie': cookie
}
self.mp4_headers = {
'Content-Type': 'video/mp4'
}
self.le_id = le_id
self.course_list = None
@staticmethod
def get_current_file_dir():
return os.path.abspath(os.path.dirname(__file__))
@staticmethod
def dict2str(dct):
items = [f'{key}={value}' for key, value in dct.items()]
return '&'.join(items)
@staticmethod
def get_sid():
return random.random()
def study_mp4(self, info):
data = {
'flag': 'studyMp4',
'le_id': self.le_id,
'preview': 1,
'mp4Id': info['id'],
'duration': 0,
'sid': self.get_sid()
}
url = self.lesson_action_main_url + '?' + self.dict2str(data)
res = requests.get(url, headers=self.html_headers)
if res.status_code != 200:
print('study_mp4请求异常')
else:
print('study_mp4请求正常')
def go_to_student(self):
data = {
'flag': 'gotoStudent20140504'
}
url = self.website_action_main_url + '?' + self.dict2str(data)
res = requests.post(url, headers=self.json_headers)
if res.status_code != 200:
print('go_to_student请求异常')
else:
print('go_to_student请求正常')
def get_lesson_chapter(self):
data = {
'flag': 'getLessonChapter',
'le_id': self.le_id,
'sid': self.get_sid()
}
url = self.lesson_action_main_url + '?' + self.dict2str(data)
res = requests.post(url, headers=self.json_headers)
if res.status_code != 200:
print('请求课程列表异常')
else:
data_dict = json.loads(res.text)
course_data = data_dict['data']
details = [each['details'] for each in course_data]
# 压平 过滤已学部分
self.course_list = [i for sublist in details for i in sublist if i['schedule'] < 100]
@staticmethod
def download_mp4(url, save_path):
try:
# 创建会话并设置重试机制
session = requests.Session()
retries = Retry(total=5, backoff_factor=1, status_forcelist=[502, 503, 504])
session.mount('https://', HTTPAdapter(max_retries=retries))
res = session.get(url, stream=True, timeout=30)
res.raise_for_status() # 确保请求成功
# 获取文件总大小
# total_size = int(res.headers.get('content-length', 0))
# print(f'视频总大小: {total_size}字节')
# 逐块下载并保存到本地文件
with open(save_path, 'wb') as f:
for chunk in res.iter_content(chunk_size=8192):
if chunk:
f.write(chunk)
print(f'视频下载完成,保存路径: {save_path}')
except requests.exceptions.RequestException as e:
print(f'视频下载失败: {e}')
@staticmethod
def get_video_duration(video_path):
try:
if not os.path.isfile(video_path):
print(f"视频文件路径错误: {video_path}")
return None
# 使用 ffmpeg 获取视频时长
result = subprocess.run(
["ffprobe", "-v", "error", "-show_entries", "format=duration", "-of",
"default=noprint_wrappers=1:nokey=1", video_path],
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT
)
duration = round(float(result.stdout.decode().strip()), 2)
print(f"视频时长:{duration} 秒")
return duration
except Exception as e:
print(f"获取视频时长失败:{e}")
return None
def update_mp4_time(self, info):
data = {
'flag': 'updateMp4Time',
'le_id': self.le_id,
'mp4Id': info['id'],
'totalTime': info['totalTime']
}
url = self.lesson_action_main_url + '?' + self.dict2str(data)
res = requests.post(url, headers=self.json_headers)
if res.status_code != 200:
print('update_mp4_time请求返回异常')
else:
print('update_mp4_time请求成功')
def update_time(self, info):
data = {
'flag': 'updateTime',
'le_id': self.le_id,
'mp4Id': info['id']
}
url = self.lesson_action_main_url + '?' + self.dict2str(data)
res = requests.post(url, headers=self.json_headers)
if res.status_code != 200:
print('update_time请求返回异常')
else:
print('update_time请求成功')
def update_study_statistics_info(self, index, info, current_time):
data = {
'flag': 'updateStudyStatisticsInfo',
'le_id': self.le_id,
'mp4Id': info['id'],
'currentTime': current_time,
'sid': self.get_sid()
}
url = self.lesson_action_main_url + '?' + self.dict2str(data)
res = requests.post(url, headers=self.json_headers)
if res.status_code != 200:
print(f'第{index + 1}次update_study_statistics_info请求返回异常: {current_time}s')
else:
print(f'第{index + 1}次update_study_statistics_info请求成功: {current_time}s')
return res
if __name__ == '__main__':
my_cookie = '*******************'
lesson_id = 'cd73ea2304d54b0596fc48c560a6be9d'
courseLearning = CourseLearning(my_cookie, lesson_id)
# 1. 获取学习列表
courseLearning.get_lesson_chapter()
if not courseLearning.course_list:
print('学习列表为空或已学完')
for item in courseLearning.course_list:
print('=====课程章节[%s], 课程名称[%s]=====' % (item['chapter'], item['le_name']))
# 2. 请求开始学习
courseLearning.study_mp4(item)
# courseLearning.go_to_student()
mp4_download_url = courseLearning.mp4_main_url + item['enter_url']
mp4_name = item['enter_url'].split('/')[-1]
mp4_save_path = courseLearning.mp4_save_dir + os.sep + mp4_name
# 3.下载视频,并获取视频时长
courseLearning.download_mp4(mp4_download_url, mp4_save_path)
item['totalTime'] = courseLearning.get_video_duration(mp4_save_path)
if item['totalTime'] is None:
raise TypeError('视频时长为None')
# 4.更新mp4时长
courseLearning.update_mp4_time(item)
# 5.更新时间
courseLearning.update_time(item)
# 6.每分钟更新播放信息
total_index = int(item['totalTime'] / 60) + 1
for i in range(total_index):
time.sleep(10)
seed_second = round(random.random() * 0.5, 2)
curr_time = ((i + 1) * 60 - seed_second) if i < total_index - 1 else item['totalTime']
resp = courseLearning.update_study_statistics_info(i, item, curr_time)
if resp.status_code != 200:
break
God will send the rain when you are ready.You need to prepare your field to receive it.