Python3 【项目实战】深度解析:电影马拉松时长分析工具
一、项目背景
在流媒体平台普及的今天,用户常连续观看多部电影或剧集(称为“观影马拉松”)。分析用户观影日志,帮助用户了解自己的观影习惯,并避免过度疲劳,开发此工具用于分析观影记录,统计总时长、平均单次时长及最长连续观看时间,辅助用户合理规划时间。
二、项目功能
- 输入:观影日志列表,每条记录包含开始时间(
"YYYY-MM-DD HH:MM"
)和观影时长(分钟)。 - 处理:
- 计算总观看时长、平均单次时长
- 识别连续观看时间段(无间隔或重叠)
- 确定最长连续观看时长
- 输出:字典格式统计结果。
print(analyze_movie_marathon(watch_log)) # 输出示例:{'total_minutes': 360, 'avg_minutes': 120.0, 'max_continuous': 150}
三、实现原理
- 时间处理:
- 将字符串时间转为
datetime
对象 - 计算每次观影的结束时间(开始时间 + 时长)
- 将字符串时间转为
- 连续区间合并:
- 若当前观影开始时间 ≤ 上一次观影结束时间,合并为同一连续区间
- 否则视为新区间
- 统计计算:
- 遍历合并后的区间列表,计算最长连续时长
四、代码实现
from datetime import datetime, timedelta
# 模拟观影日志(格式:开始时间)
watch_log = [
("2023-10-05 09:00", 120), # 开始时间 + 分钟数
("2023-10-05 11:30", 90),
("2023-10-05 14:00", 150)
]
def analyze_movie_marathon(logs):
total_duration = sum(duration for _, duration in logs)
avg_duration = total_duration / len(logs)
# 计算连续观看时间(假设按时间顺序排列)
intervals = []
prev_end = None
for start_str, duration in logs:
start = datetime.strptime(start_str, "%Y-%m-%d %H:%M")
end = start + timedelta(minutes=duration)
if prev_end and start <= prev_end:
intervals[-1] = (intervals[-1][0], end)
else:
intervals.append((start, end))
prev_end = end
max_interval = max(intervals, key=lambda x: x[1] - x[0], default=None)
max_duration = (max_interval[1] - max_interval[0]).seconds // 60 if max_interval else 0
return {
"total_minutes": total_duration,
"avg_minutes": round(avg_duration, 1),
"max_continuous": max_duration
}
print(analyze_movie_marathon(watch_log))
五、代码解析
def analyze_movie_marathon(logs):
# 总时长与平均值计算
total_duration = sum(duration for _, duration in logs)
avg_duration = total_duration / len(logs)
# 连续区间合并逻辑
intervals = []
prev_end = None # 跟踪上一个区间的结束时间
for start_str, duration in logs:
start = datetime.strptime(start_str, "%Y-%m-%d %H:%M")
end = start + timedelta(minutes=duration)
# 合并重叠/连续区间
if prev_end and start <= prev_end:
intervals[-1] = (intervals[-1][0], end) # 合并区间
else:
intervals.append((start, end)) # 新区间
prev_end = end # 更新跟踪的结束时间
# 计算最长连续时长
max_interval = max(intervals, key=lambda x: x[1] - x[0], default=None)
max_duration = (max_interval[1] - max_interval[0]).seconds // 60 if max_interval else 0
return {
"total_minutes": total_duration,
"avg_minutes": round(avg_duration, 1),
"max_continuous": max_duration
}
六、测试用例
-
正常输入(用户示例):
watch_log = [ ("2023-10-05 09:00", 120), ("2023-10-05 11:30", 90), ("2023-10-05 14:00", 150) ] # 预期输出:总时长=360,平均=120.0,最长连续=150
-
连续观看场景:
watch_log = [ ("2023-10-05 09:00", 60), ("2023-10-05 10:00", 120) # 紧接前一次结束 ] # 预期输出:最长连续=180(合并后总时长)
-
跨天观看:
watch_log = [ ("2023-10-05 23:30", 150) # 结束时间为次日02:00 ] # 当前代码输出错误(需优化跨天处理)
七、执行结果
# 用户示例执行结果
{'total_minutes': 360, 'avg_minutes': 120.0, 'max_continuous': 150}
八、项目优化
-
跨天观看支持:
使用total_seconds()
替代seconds
处理超过24小时的间隔:max_duration = (max_interval[1] - max_interval[0]).total_seconds() // 60
-
输入顺序校验:
强制按开始时间排序日志,避免乱序导致合并错误:logs.sort(key=lambda x: datetime.strptime(x[0], "%Y-%m-%d %H:%M"))
-
异常处理:
添加对无效时间格式和负时长的校验:try: start = datetime.strptime(start_str, "%Y-%m-%d %H:%M") except ValueError: raise ValueError(f"无效时间格式:{start_str}") if duration < 0: raise ValueError("观影时长不可为负数")
九、项目展望
-
可视化时间线:
使用matplotlib
绘制观影区间甘特图,直观展示连续观看时段。import matplotlib.pyplot as plt plt.barh(y=0, width=max_duration, left=start_time)
-
健康提醒功能:
若单次连续观看超过阈值(如4小时),触发休息提醒:if max_duration > 240: print("警告:单次观看时间过长!")
-
平台数据集成:
对接 Netflix/Disney+ 等平台的观看历史API,自动获取数据。 -
社交分享:
生成观影报告海报,支持分享至社交媒体。
总结
该工具通过时间合并算法精准识别连续观影行为,为用户提供量化数据参考。通过优化跨天处理和输入校验,可扩展至更复杂的真实场景,成为流媒体平台用户健康管理的重要组成部分。