三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

个人音乐数据仪表盘:跨平台听歌记录分析与可视化

个人音乐数据仪表盘:跨平台听歌记录分析与可视化

1. 项目概述:打造个人音乐数据仪表盘

去年整理硬盘时,偶然发现自己的音乐播放记录分散在五六个平台,突然萌生了个想法:要是能把这些数据统一分析,说不定能发现些有趣的听歌模式。这个项目就是通过抓取各平台的听歌记录,建立个人音乐数据库,实现三个核心功能:

  • 自动统计每周/月/年的听歌总时长
  • 可视化展示不同时段的听歌偏好变化
  • 基于音频特征分析音乐风格分布

我最终实现的系统每周自动生成这样的报告:"上周共聆听14小时37分钟,工作日平均每天2小时,周末达3.5小时。电子音乐占比提升12%,特别是周五晚间出现Trance音乐高峰期。"

2. 数据采集方案设计

2.1 主流平台API对接

各大音乐平台都提供了开发者接口,但权限和数据结构差异较大:

平台接口类型关键字段获取难度
SpotifyWeb APItrack, duration, played_at★★☆☆☆
网易云音乐私有APIsong, playTime, source★★★★☆
Apple MusicApple MusicKitplayDate, songDuration★★★☆☆
Last.fmScrobbler APIartist, track, timestamp★★☆☆☆

实操建议:优先从Last.fm入手,它记录了跨平台的播放历史。网易云需要抓包分析手机端接口,建议使用Charles等工具。

2.2 本地音乐文件处理

对于本地存储的MP3/FLAC文件,我用Python的mutagen库提取ID3标签:

from mutagen.id3 import ID3 audio = ID3("song.mp3") print({ 'title': audio.get('TIT2').text[0], 'artist': audio.get('TPE1').text[0], 'duration': audio.info.length })

3. 核心分析模块实现

3.1 时长统计逻辑

关键是要处理不同来源的时间格式统一问题。比如Spotify返回的是ISO 8601格式("2023-07-15T14:30:22Z"),而网易云是Unix时间戳(毫秒级):

def normalize_time(time_str): if isinstance(time_str, int): # 处理时间戳 return datetime.fromtimestamp(time_str/1000) elif 'T' in time_str: # 处理ISO格式 return datetime.strptime(time_str, '%Y-%m-%dT%H:%M:%SZ') else: return datetime.strptime(time_str, '%Y-%m-%d %H:%M:%S')

3.2 音乐风格分析方案

我测试了两种技术路线:

  1. 基于标签的分类:利用Last.fm的track.getTopTags方法
  2. 基于音频特征的聚类:使用librosa提取MFCC特征后做K-means聚类

实测发现第一种方案准确度更高,特别是对于中文歌曲。以下是特征提取代码片段:

import librosa y, sr = librosa.load('song.mp3') mfcc = librosa.feature.mfcc(y=y, sr=sr, n_mfcc=13)

4. 可视化与报告生成

4.1 听歌时段热力图

用Plotly生成交互式热力图,清晰展示不同时段的听歌强度:

import plotly.express as px fig = px.density_heatmap( df, x="hour", y="weekday", z="duration", histfunc="sum" ) fig.update_layout(title='Weekly Listening Pattern')

4.2 风格偏好雷达图

将音乐风格占比数据转化为六维雷达图,突出偏好变化:

时间周期流行摇滚电子古典嘻哈爵士
2023年第1周35%20%15%10%15%5%
2023年第2周30%25%18%8%12%7%

5. 踩坑实录与优化建议

  1. 时区问题:某次发现周末数据异常,原来是网易云返回的是北京时间戳,而Spotify是UTC时间。解决方案:
# 统一转换为本地时区 from pytz import timezone beijing = timezone('Asia/Shanghai') utc_time.replace(tzinfo=timezone('UTC')).astimezone(beijing)
  1. 歌曲去重:不同平台对同一首歌的命名差异很大(比如包含/不包含feat信息),我最终采用fuzzywuzzy进行模糊匹配:
from fuzzywuzzy import fuzz if fuzz.ratio(title1, title2) > 85: # 判定为同一歌曲
  1. 性能优化:当记录超过10万条时,Pandas处理明显变慢。这两个技巧很有效:
  • 将datetime列转为period类型
  • 对artist列使用category数据类型

这个项目最让我意外的发现是:每当项目截止日前三天,我的电子音乐收听量会暴涨200%。看来大脑在高压状态下确实需要特定类型的音乐刺激。现在我会根据这些数据主动调整播放列表,比如周一下午安排些轻音乐对抗"周一综合征"。

← 返回列表