1. 项目概述:解锁你的音乐DNA
作为一名长期使用Spotify的音乐爱好者,我发现自己经常在播放列表中反复听某些歌曲,却从未系统分析过自己的听歌习惯。直到某天发现Spotify开发者平台提供了完整的API接口,才意识到可以用Python将这些数据转化为可视化的音乐画像。这个项目不仅能展示你最喜欢的艺术家、常听的曲风,还能揭示你不同时段的音乐偏好变化。
通过分析自己的Spotify数据,我发现了许多有趣的现象:比如工作日早晨会不自觉地播放更多电子音乐,而周末深夜则倾向于民谣;去年夏天循环播放的歌曲现在几乎不再触碰。这些发现让我开始思考音乐品味如何随时间演变,以及外部环境对听歌选择的影响。
2. 技术准备与环境搭建
2.1 获取Spotify API访问权限
首先需要在Spotify开发者仪表板创建应用。注册后会获得CLIENT_ID和CLIENT_SECRET这两个关键凭证。建议将凭证存储在环境变量中而非直接写在代码里:
bash复制export SPOTIPY_CLIENT_ID='your_client_id'
export SPOTIPY_CLIENT_SECRET='your_client_secret'
export SPOTIPY_REDIRECT_URI='http://localhost:8888/callback'
注意:redirect_URI必须与开发者仪表板中设置的白名单完全匹配,否则会报错
2.2 安装必要的Python库
推荐使用conda创建专属虚拟环境:
bash复制conda create -n spotify-analysis python=3.8
conda activate spotify-analysis
pip install spotipy pandas matplotlib seaborn
其中spotipy是Spotify官方维护的Python SDK,封装了所有API调用逻辑。pandas用于数据处理,matplotlib和seaborn则是可视化利器。
2.3 认证流程实现
使用OAuth2授权码流程获取访问令牌:
python复制import spotipy
from spotipy.oauth2 import SpotifyOAuth
scope = "user-library-read user-top-read user-read-recently-played"
sp = spotipy.Spotify(auth_manager=SpotifyOAuth(scope=scope))
# 测试API连通性
current_user = sp.current_user()
print(f"成功连接: {current_user['display_name']}")
首次运行会弹出浏览器窗口要求登录Spotify账号并授权。成功后会在本地生成.cache文件存储令牌,后续调用无需重复认证。
3. 数据采集与清洗
3.1 获取听歌历史记录
Spotify提供多种时间维度的听歌数据:
python复制# 获取最近50条播放记录
recent_tracks = sp.current_user_recently_played(limit=50)
# 获取短期(约4周)和长期(约6个月)最常听的艺术家/曲目
top_artists = sp.current_user_top_artists(time_range='short_term', limit=20)
top_tracks = sp.current_user_top_tracks(time_range='long_term', limit=50)
3.2 数据结构化处理
将API返回的JSON数据转换为pandas DataFrame:
python复制import pandas as pd
def parse_track(track):
return {
'name': track['name'],
'artist': ', '.join([a['name'] for a in track['artists']]),
'duration_ms': track['duration_ms'],
'popularity': track['popularity'],
'album': track['album']['name'],
'release_date': track['album']['release_date'],
'explicit': track['explicit']
}
tracks_df = pd.DataFrame([parse_track(item['track']) for item in recent_tracks['items']])
3.3 补充音频特征数据
Spotify为每首歌曲提供了详细的音频特征分析:
python复制audio_features = sp.audio_features(tracks_df.index.tolist())
features_df = pd.DataFrame(audio_features).drop(['type', 'uri', 'track_href', 'analysis_url'], axis=1)
这些特征包括:
- danceability(舞蹈性):0-1,节奏规律性
- energy(能量感):0-1,强度与活跃度
- valence(愉悦度):0-1,音乐情绪积极程度
- tempo(速度):BPM值
- speechiness(语言含量):说唱vs纯音乐
- acousticness(原声程度):电子合成vs原声乐器
4. 数据分析与可视化
4.1 基础统计指标
python复制print(f"平均歌曲时长: {tracks_df['duration_ms'].mean()/60000:.2f}分钟")
print(f"显式内容占比: {tracks_df['explicit'].mean()*100:.1f}%")
print(f"最新歌曲发行于: {tracks_df['release_date'].max()}")
4.2 艺术家出现频率分析
python复制from collections import Counter
artist_list = [artist for sublist in tracks_df['artist'].str.split(', ') for artist in sublist]
top_artists = Counter(artist_list).most_common(5)
4.3 音频特征雷达图
python复制import matplotlib.pyplot as plt
import numpy as np
features = ['danceability', 'energy', 'speechiness', 'acousticness', 'valence']
values = features_df[features].mean().tolist()
values += values[:1] # 闭合雷达图
angles = np.linspace(0, 2*np.pi, len(features), endpoint=False).tolist()
angles += angles[:1]
fig, ax = plt.subplots(figsize=(8,8), subplot_kw={'polar': True})
ax.plot(angles, values, linewidth=1, linestyle='solid', label='我的听歌特征')
ax.fill(angles, values, alpha=0.25)
ax.set_xticks(angles[:-1])
ax.set_xticklabels(features)
ax.set_title('音频特征雷达图', pad=20)
plt.show()
4.4 听歌时间模式分析
通过播放记录的时间戳分析听歌时段偏好:
python复制tracks_df['played_at'] = pd.to_datetime([item['played_at'] for item in recent_tracks['items']])
tracks_df['hour'] = tracks_df['played_at'].dt.hour
plt.figure(figsize=(10,6))
sns.countplot(data=tracks_df, x='hour', palette='viridis')
plt.title('不同时段的听歌频率分布')
plt.xlabel('小时')
plt.ylabel('播放次数')
5. 高级分析技巧
5.1 音乐品味聚类分析
使用K-means对常听歌曲进行风格聚类:
python复制from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler
X = features_df[['danceability', 'energy', 'valence', 'tempo']]
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
kmeans = KMeans(n_clusters=3, random_state=42)
tracks_df['cluster'] = kmeans.fit_predict(X_scaled)
# 可视化聚类结果
plt.scatter(tracks_df['danceability'], tracks_df['energy'], c=tracks_df['cluster'], cmap='viridis')
plt.xlabel('Danceability')
plt.ylabel('Energy')
5.2 音乐情绪时间线
结合valence值绘制情绪变化曲线:
python复制tracks_df['date'] = tracks_df['played_at'].dt.date
daily_mood = tracks_df.groupby('date')['valence'].mean()
plt.figure(figsize=(12,4))
daily_mood.plot(kind='line', marker='o')
plt.axhline(y=0.5, color='r', linestyle='--')
plt.title('每日平均音乐情绪变化')
plt.ylabel('Valence (愉悦度)')
5.3 生成个性化歌单
基于分析结果自动创建推荐歌单:
python复制# 找出高能量但低愉悦度的歌曲 - 适合运动时听
workout_tracks = tracks_df[(tracks_df['energy']>0.8) & (tracks_df['valence']<0.4)].index.tolist()
playlist = sp.user_playlist_create(
user=current_user['id'],
name='数据分析推荐 - 运动专用',
public=False,
description='根据音频特征自动生成的健身歌单'
)
sp.playlist_add_items(playlist['id'], workout_tracks)
6. 常见问题与解决方案
6.1 API调用频率限制
Spotify API有严格的速率限制:
- 常规请求:30次/秒
- 音频分析请求:5次/秒
建议添加延迟避免触发限制:
python复制import time
for track_id in track_ids:
features = sp.audio_features(track_id)
time.sleep(0.2) # 控制请求频率
6.2 数据不完整问题
最近播放记录最多只能获取最近50条。如需更全面数据,建议:
- 定期运行脚本收集数据
- 使用Spotify的"导出数据"功能获取完整历史
- 结合第三方服务如Last.fm记录播放历史
6.3 音频特征解释差异
某些特征如valence可能不符合个人主观感受。这是因为:
- 算法基于大众标注而非个人感知
- 文化差异会影响情绪判断
- 歌曲不同段落可能有不同情绪
建议结合多个特征综合判断,或自行标注部分歌曲建立个人化模型。
7. 项目扩展方向
7.1 长期追踪音乐品味变化
设置定时任务每周收集数据,建立时间序列数据库:
python复制import schedule
import time
def collect_data():
# 收集数据并存储到CSV或数据库
pass
schedule.every().sunday.at("03:00").do(collect_data)
while True:
schedule.run_pending()
time.sleep(60)
7.2 构建音乐推荐系统
基于历史数据训练简单的推荐模型:
python复制from sklearn.neighbors import NearestNeighbors
model = NearestNeighbors(n_neighbors=5, algorithm='ball_tree')
model.fit(features_df[features])
# 为当前歌曲找相似歌曲
distances, indices = model.kneighbors([features_df.iloc[0][features]])
similar_tracks = tracks_df.iloc[indices[0]]
7.3 创建交互式仪表盘
使用Plotly Dash构建可视化面板:
python复制import dash
from dash import dcc, html
app = dash.Dash(__name__)
app.layout = html.Div([
dcc.Graph(figure=create_radar_chart()),
dcc.Graph(figure=create_time_series())
])
if __name__ == '__main__':
app.run_server(debug=True)
这个项目最让我惊喜的是发现了自己音乐品味中那些未曾察觉的模式。比如数据显示我在阴雨天会不自觉地选择更多小调歌曲,而编程时则偏好没有歌词的电子音乐。这些发现让我更了解音乐如何反映和影响自己的情绪状态。