add music analyzer

This commit is contained in:
mariotgb 2026-03-25 19:16:22 +03:00
parent 300cd22d50
commit 8ab6678ee1
3 changed files with 271 additions and 0 deletions

20
data/data.txt Normal file
View File

@ -0,0 +1,20 @@
1|Smells Like Teen Spirit|Nirvana|Nevermind|rock|301|980000|75000|1991-09-10|false
2|Blinding Lights|The Weeknd|After Hours|pop|200|1500000|120000|2019-11-29|false
3|Lose Yourself|Eminem|8 Mile|hip-hop|326|1200000|98000|2002-10-28|true
4|Levels|Avicii|True|electronic|193|870000|65000|2011-10-28|false
5|Come As You Are|Nirvana|Nevermind|rock|219|750000|58000|1992-03-02|false
6|Starboy|The Weeknd|Starboy|pop|230|1100000|88000|2016-09-22|true
7|Rap God|Eminem|The Marshall Mathers LP2|hip-hop|363|950000|82000|2013-10-14|true
8|Wake Me Up|Avicii|True|electronic|247|920000|71000|2013-06-17|false
9|In Bloom|Nirvana|Nevermind|rock|255|620000|47000|1992-11-30|false
10|Save Your Tears|The Weeknd|After Hours|pop|215|1050000|91000|2020-08-06|false
11|Without Me|Eminem|The Eminem Show|hip-hop|290|880000|69000|2002-05-14|true
12|Hey You|Pink Floyd|The Wall|rock|277|540000|49000|1979-11-30|false
13|Wish You Were Here|Pink Floyd|Wish You Were Here|rock|334|670000|61000|1975-09-12|false
14|Scared to Be Lonely|Avicii|Avicii 01|electronic|211|430000|38000|2017-02-03|false
15|Die For You|The Weeknd|Starboy|pop|260|990000|95000|2016-11-25|false
16|Godzilla|Eminem|Music to Be Murdered By|hip-hop|213|760000|55000|2020-01-17|true
17|Money|Pink Floyd|The Dark Side of the Moon|rock|382|590000|53000|1973-03-01|false
18|The Night|Avicii|Stories|electronic|198|380000|29000|2015-10-02|false
19|Lithium|Nirvana|Nevermind|rock|256|690000|52000|1992-07-21|false
20|Take My Breath|The Weeknd|Dawn FM|pop|223|820000|74000|2021-08-06|false

241
music_analyzer.py Normal file
View File

@ -0,0 +1,241 @@
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()

10
results/top_tracks.txt Normal file
View File

@ -0,0 +1,10 @@
Blinding Lights | The Weeknd | pop | 1500000 прослушиваний
Lose Yourself | Eminem | hip-hop | 1200000 прослушиваний
Starboy | The Weeknd | pop | 1100000 прослушиваний
Save Your Tears | The Weeknd | pop | 1050000 прослушиваний
Die For You | The Weeknd | pop | 990000 прослушиваний
Smells Like Teen Spirit | Nirvana | rock | 980000 прослушиваний
Rap God | Eminem | hip-hop | 950000 прослушиваний
Wake Me Up | Avicii | electronic | 920000 прослушиваний
Without Me | Eminem | hip-hop | 880000 прослушиваний
Levels | Avicii | electronic | 870000 прослушиваний