MusicAnalyzer/music_analyzer.py
2026-03-25 19:16:22 +03:00

241 lines
7.9 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import os
def load_tracks(filepath):
"""Загружает треки из txt файла. При ошибке возвращает пустой список."""
tracks = []
try:
with open(filepath, "r", encoding="utf-8") as f:
for line in f:
line = line.strip()
# пропускаем пустые строки
if not line:
continue
parts = line.split("|")
# проверяем что полей ровно 10
if len(parts) != 10:
print("Пропускаю некорректную строку:", line)
continue
track = {
"track_id": int(parts[0]),
"title": parts[1],
"artist": parts[2],
"album": parts[3],
"genre": parts[4],
"duration_seconds": int(parts[5]),
"plays": int(parts[6]),
"likes": int(parts[7]),
"release_date": parts[8],
"explicit": parts[9] == "true"
}
tracks.append(track)
except FileNotFoundError:
print("Файл не найден:", filepath)
return []
return tracks
def filter_by_genre(tracks, genre):
"""Возвращает треки с указанным жанром."""
result = []
for track in tracks:
if track["genre"].lower() == genre.lower():
result.append(track)
return result
def filter_by_duration(tracks, min_sec, max_sec):
"""Возвращает треки с длительностью в диапазоне [min_sec, max_sec]."""
result = []
for track in tracks:
if min_sec <= track["duration_seconds"] <= max_sec:
result.append(track)
return result
def get_top_tracks(tracks, n):
"""Возвращает n треков с наибольшим числом прослушиваний."""
sorted_tracks = sorted(tracks, key=lambda t: t["plays"], reverse=True)
return sorted_tracks[:n]
def calculate_artist_stats(tracks, artist):
"""Возвращает статистику по исполнителю."""
artist_tracks = []
for track in tracks:
if track["artist"].lower() == artist.lower():
artist_tracks.append(track)
if len(artist_tracks) == 0:
return {
"total_tracks": 0,
"total_plays": 0,
"total_likes": 0,
"avg_duration_seconds": 0.0
}
total_plays = 0
total_likes = 0
total_duration = 0
for track in artist_tracks:
total_plays += track["plays"]
total_likes += track["likes"]
total_duration += track["duration_seconds"]
avg_duration = total_duration / len(artist_tracks)
return {
"total_tracks": len(artist_tracks),
"total_plays": total_plays,
"total_likes": total_likes,
"avg_duration_seconds": round(avg_duration, 2)
}
def get_unique_genres(tracks):
"""Возвращает отсортированный список уникальных жанров."""
genres = []
for track in tracks:
if track["genre"] not in genres:
genres.append(track["genre"])
return sorted(genres)
def calculate_like_rate(tracks):
"""Считает коэффициент лайков для каждого трека."""
result = []
for track in tracks:
if track["plays"] == 0:
continue
rate = track["likes"] / track["plays"] * 100
rate = round(rate, 2)
result.append((track["title"], rate))
result = sorted(result, key=lambda x: x[1], reverse=True)
return result
def group_by_artist(tracks):
"""Группирует треки по исполнителю."""
result = {}
for track in tracks:
artist = track["artist"]
if artist not in result:
result[artist] = []
result[artist].append(track)
return result
def filter_by_date_range(tracks, date_from, date_to):
"""Возвращает треки выпущенные в диапазоне дат."""
result = []
for track in tracks:
if date_from <= track["release_date"] <= date_to:
result.append(track)
return result
def save_report(data, filepath):
"""Сохраняет список треков в txt файл."""
try:
directory = os.path.dirname(filepath)
if directory and not os.path.exists(directory):
os.makedirs(directory)
with open(filepath, "w", encoding="utf-8") as f:
for track in data:
line = "{title} | {artist} | {genre} | {plays} прослушиваний\n".format(
title=track["title"],
artist=track["artist"],
genre=track["genre"],
plays=track["plays"]
)
f.write(line)
return True
except Exception as e:
print("Ошибка при сохранении файла:", e)
return False
def main():
# 1. Загружаем треки
tracks = load_tracks("data/data.txt")
if len(tracks) == 0:
print("Нет данных для обработки")
return
# 2. Общее количество треков и жанры
print("=" * 40)
print("Всего треков:", len(tracks))
genres = get_unique_genres(tracks)
print("Жанры:", ", ".join(genres))
# 3. Фильтрация по жанру
print("=" * 40)
rock_tracks = filter_by_genre(tracks, "rock")
print("Треков в жанре rock:", len(rock_tracks))
# 4. Топ-5 треков по прослушиваниям
print("=" * 40)
print("Топ-5 треков по прослушиваниям:")
top5 = get_top_tracks(tracks, 5)
for track in top5:
print(" -", track["title"], "", track["plays"], "прослушиваний")
# 5. Статистика исполнителя
print("=" * 40)
first_artist = tracks[0]["artist"]
stats = calculate_artist_stats(tracks, first_artist)
print("Статистика исполнителя:", first_artist)
print(" - Треков:", stats["total_tracks"])
print(" - Прослушиваний:", stats["total_plays"])
print(" - Лайков:", stats["total_likes"])
print(" - Средняя длительность (сек):", stats["avg_duration_seconds"])
# 6. Фильтрация по длительности
print("=" * 40)
mid_tracks = filter_by_duration(tracks, 180, 240)
print("Треков длительностью 3-4 минуты:", len(mid_tracks))
# 7. Топ-5 по коэффициенту лайков
print("=" * 40)
print("Топ-5 треков по лайкам:")
like_rates = calculate_like_rate(tracks)
for title, rate in like_rates[:5]:
print(" -", title, "", rate, "%")
# 8. Фильтрация по дате
print("=" * 40)
date_filtered = filter_by_date_range(tracks, "2020-01-01", "2024-12-31")
print("Треков за период 2020-2024:", len(date_filtered))
# 9. Группировка по исполнителям
print("=" * 40)
print("Треков по исполнителям:")
grouped = group_by_artist(tracks)
for artist, artist_tracks in grouped.items():
print(" -", artist, ":", len(artist_tracks), "треков")
# 10. Сохраняем топ-10 в файл
print("=" * 40)
top10 = get_top_tracks(tracks, 10)
success = save_report(top10, "results/top_tracks.txt")
if success:
print("Топ-10 треков сохранён в results/top_tracks.txt")
else:
print("Не удалось сохранить файл")
if __name__ == "__main__":
main()