1. 项目概述:用Python解锁你的Spotify听歌数据
作为一名长期使用Spotify的音乐爱好者,我发现自己经常好奇:我到底听了多少首歌?最常听的歌手是谁?不同时段的听歌偏好有什么变化?直到我发现Spotify Web API和Python的spotipy库,才真正打开了音乐数据分析的大门。
Spotify不仅是个音乐平台,更是个数据宝库。通过其开放的API接口,我们可以获取包括播放历史、收藏歌单、歌曲特征等在内的完整听歌数据。而Python凭借其丰富的数据分析库,能够将这些原始数据转化为直观的洞察。这就像给你的音乐品味做了次全面体检,结果可能会让你大吃一惊。
2. 环境准备与API配置
2.1 创建Spotify开发者应用
要访问Spotify API,首先需要在Spotify开发者仪表板创建应用:
- 登录Spotify开发者网站
- 点击"Create an App"
- 填写应用名称和描述(如"My Listening Analysis")
- 创建后记录下Client ID和Client Secret
重要提示:Client Secret相当于应用密码,绝不能泄露。我习惯将其保存在环境变量中而非直接写在代码里。
2.2 安装必要的Python库
推荐使用pip安装以下库:
bash复制pip install spotipy pandas matplotlib seaborn
- spotipy:Spotify API的Python客户端库
- pandas:数据处理与分析
- matplotlib/seaborn:数据可视化
2.3 配置认证流程
Spotify API使用OAuth 2.0认证。以下是初始化spotipy客户端的代码模板:
python复制import spotipy
from spotipy.oauth2 import SpotifyOAuth
# 设置环境变量或直接替换为你的凭证
SPOTIPY_CLIENT_ID = 'your_client_id'
SPOTIPY_CLIENT_SECRET = 'your_client_secret'
SPOTIPY_REDIRECT_URI = 'http://localhost:8888/callback' # 本地开发常用回调地址
# 定义需要的权限范围
scope = "user-library-read user-read-recently-played user-top-read"
sp = spotipy.Spotify(auth_manager=SpotifyOAuth(
client_id=SPOTIPY_CLIENT_ID,
client_secret=SPOTIPY_CLIENT_SECRET,
redirect_uri=SPOTIPY_REDIRECT_URI,
scope=scope))
第一次运行时会自动打开浏览器要求登录Spotify账号并授权。授权后会在本地生成.cache文件存储令牌,后续请求无需重复授权。
3. 获取核心听歌数据
3.1 获取近期播放历史
分析听歌行为的基础是获取播放记录。Spotify提供最近50条播放历史:
python复制def get_recent_tracks(limit=50):
results = sp.current_user_recently_played(limit=limit)
tracks = []
for item in results['items']:
track = item['track']
tracks.append({
'played_at': item['played_at'],
'name': track['name'],
'artist': ', '.join([a['name'] for a in track['artists']]),
'duration_ms': track['duration_ms'],
'popularity': track['popularity'],
'id': track['id']
})
return pd.DataFrame(tracks)
这个函数返回包含歌曲名称、艺术家、播放时间等信息的DataFrame。我添加了played_at解析,方便后续按时间分析:
python复制df['played_at'] = pd.to_datetime(df['played_at'])
df['hour'] = df['played_at'].dt.hour
3.2 获取最常播放的歌曲和艺人
Spotify提供三个时间维度的top记录:短期(约4周)、中期(约6个月)和长期(数年):
python复制def get_top_items(item_type='tracks', time_range='medium_term', limit=20):
if item_type == 'tracks':
results = sp.current_user_top_tracks(time_range=time_range, limit=limit)
return pd.DataFrame([{
'name': item['name'],
'artist': ', '.join([a['name'] for a in item['artists']]),
'popularity': item['popularity'],
'id': item['id']
} for item in results['items']])
else:
results = sp.current_user_top_artists(time_range=time_range, limit=limit)
return pd.DataFrame([{
'name': item['name'],
'genres': ', '.join(item['genres']),
'popularity': item['popularity'],
'id': item['id']
} for item in results['items']])
3.3 获取歌曲音频特征
Spotify为每首歌提供了详细的音频特征分析,包括节奏、调性、情绪等:
python复制def get_audio_features(track_ids):
features = []
# spotipy每次最多获取100首歌的特征
for i in range(0, len(track_ids), 100):
batch = track_ids[i:i+100]
features += sp.audio_features(batch)
return pd.DataFrame(features)
这些特征包括:
- danceability:舞蹈性(0-1)
- energy:能量感(0-1)
- valence:情绪积极度(0-1)
- tempo:BPM速度
- key/mode:调性和调式
4. 数据分析与可视化
4.1 听歌时间分布分析
了解自己的听歌时间习惯有助于优化播放列表:
python复制import matplotlib.pyplot as plt
import seaborn as sns
def plot_listening_times(df):
plt.figure(figsize=(12, 6))
sns.countplot(x='hour', data=df, palette='viridis')
plt.title('Listening Activity by Hour of Day')
plt.xlabel('Hour of Day')
plt.ylabel('Number of Plays')
plt.show()

(实际使用时需替换为你的图表)
4.2 艺人偏好分析
使用桑基图(Sankey diagram)展示艺人之间的听歌流动:
python复制from pySankey.sankey import sankey
def plot_artist_flow(df):
# 预处理数据:计算艺人转换频率
artist_flow = df.groupby(['hour', 'artist']).size().unstack().fillna(0)
plt.figure(figsize=(15, 10))
sankey.sankey(artist_flow.sum(axis=0), artist_flow.sum(axis=1),
aspect=20, fontsize=12)
plt.title('Artist Listening Flow')
plt.show()
4.3 音乐特征雷达图
展示你的音乐品味特征:
python复制def plot_audio_profile(features_df):
categories = ['danceability', 'energy', 'valence', 'acousticness', 'instrumentalness']
stats = features_df[categories].mean().values
angles = np.linspace(0, 2*np.pi, len(categories), endpoint=False)
stats = np.concatenate((stats,[stats[0]]))
angles = np.concatenate((angles,[angles[0]]))
fig = plt.figure(figsize=(8, 8))
ax = fig.add_subplot(111, polar=True)
ax.plot(angles, stats, 'o-', linewidth=2)
ax.fill(angles, stats, alpha=0.25)
ax.set_thetagrids(angles * 180/np.pi, categories)
ax.set_title('Your Music Profile')
plt.show()
5. 高级分析与个性化推荐
5.1 创建个性化音乐画像
结合听歌历史和音频特征,可以构建你的音乐DNA:
python复制def create_music_profile(df, features_df):
profile = {
'total_tracks': len(df),
'unique_artists': df['artist'].nunique(),
'avg_popularity': df['popularity'].mean(),
'favorite_artist': df['artist'].mode()[0],
'most_common_hour': df['hour'].mode()[0]
}
# 添加音频特征
audio_stats = features_df[['danceability', 'energy', 'valence']].mean()
profile.update(audio_stats.to_dict())
return pd.Series(profile)
5.2 生成个性化推荐
基于你的听歌历史,Spotify可以提供推荐:
python复制def get_recommendations(seed_tracks=None, limit=10):
if seed_tracks is None:
# 如果没有指定种子曲目,使用最近播放的5首歌
seed_tracks = df['id'].tolist()[:5]
recommendations = sp.recommendations(
seed_tracks=seed_tracks,
limit=limit)
return pd.DataFrame([{
'name': track['name'],
'artist': ', '.join([a['name'] for a in track['artists']]),
'id': track['id']
} for track in recommendations['tracks']])
5.3 构建自动化分析流程
将上述功能整合成自动化分析脚本:
python复制def full_analysis():
print("获取近期播放历史...")
recent_tracks = get_recent_tracks()
print("获取音频特征...")
features = get_audio_features(recent_tracks['id'].tolist())
print("生成分析报告...")
plot_listening_times(recent_tracks)
plot_audio_profile(features)
profile = create_music_profile(recent_tracks, features)
print("\n=== 你的音乐画像 ===")
print(profile.to_string())
print("\n推荐你可能喜欢的歌曲:")
print(get_recommendations().to_string(index=False))
6. 实际应用与扩展思路
6.1 创建智能播放列表
基于分析结果自动创建播放列表:
python复制def create_mood_playlist(name, target_features, limit=20):
# target_features示例:{'valence': 0.8, 'energy': 0.7}
recommendations = sp.recommendations(
seed_tracks=df['id'].tolist()[:5],
limit=limit,
target_valence=target_features.get('valence'),
target_energy=target_features.get('energy'))
playlist = sp.user_playlist_create(
sp.me()['id'],
name,
public=False,
description=f"Auto-generated based on your listening habits")
sp.playlist_add_items(
playlist['id'],
[track['id'] for track in recommendations['tracks']])
return playlist
6.2 长期趋势分析
通过定期收集数据,分析音乐品味的变化:
python复制import json
from datetime import datetime
def save_snapshot():
data = {
'timestamp': datetime.now().isoformat(),
'top_tracks': get_top_items().to_dict('records'),
'top_artists': get_top_items('artists').to_dict('records')
}
with open(f'snapshot_{datetime.now().date()}.json', 'w') as f:
json.dump(data, f)
6.3 与Last.fm数据整合
如果你同时使用Last.fm,可以结合两者的数据:
python复制import pylast
def get_lastfm_data(user):
lastfm = pylast.LastFMNetwork(api_key='your_api_key')
user = lastfm.get_user(user)
return {
'weekly_artists': user.get_weekly_artist_charts(),
'loved_tracks': user.get_loved_tracks()
}
7. 遇到的挑战与解决方案
7.1 API速率限制处理
Spotify API有严格的速率限制(约每秒10次请求)。我的应对策略:
- 添加请求间隔:
python复制import time
def safe_request(func, *args, **kwargs):
try:
return func(*args, **kwargs)
except spotipy.SpotifyException as e:
if e.http_status == 429:
retry_after = int(e.headers.get('Retry-After', 1))
print(f"Hit rate limit, waiting {retry_after} seconds")
time.sleep(retry_after)
return safe_request(func, *args, **kwargs)
raise
- 缓存常用数据:
python复制from functools import lru_cache
@lru_cache(maxsize=1000)
def get_cached_track_info(track_id):
return sp.track(track_id)
7.2 数据不完整问题
近期播放历史最多只能获取50条记录。我的解决方案是定期归档数据:
python复制import os
import pandas as pd
def archive_data():
if not os.path.exists('archive'):
os.makedirs('archive')
df = get_recent_tracks()
date_str = datetime.now().date().isoformat()
df.to_csv(f'archive/{date_str}.csv', index=False)
7.3 音频特征解释
Spotify的音频特征指标专业性强,我制作了对照表帮助理解:
| 特征 | 解释 | 示例值 |
|---|---|---|
| valence | 情绪积极度(0悲伤-1快乐) | 0.75 |
| energy | 强度感知(0安静-1激烈) | 0.65 |
| danceability | 适合跳舞的程度 | 0.8 |
| acousticness | 原声音乐可能性 | 0.3 |
| instrumentalness | 无人声的可能性 | 0.05 |
8. 项目扩展与进阶方向
8.1 搭建个人音乐仪表盘
使用Flask或Dash构建Web可视化:
python复制from dash import Dash, dcc, html
app = Dash(__name__)
app.layout = html.Div([
dcc.Graph(figure=create_listening_times_chart()),
dcc.Graph(figure=create_radar_chart())
])
if __name__ == '__main__':
app.run_server(debug=True)
8.2 机器学习分类
使用听歌数据训练分类模型:
python复制from sklearn.cluster import KMeans
def cluster_tracks(features_df):
X = features_df[['danceability', 'energy', 'valence']]
kmeans = KMeans(n_clusters=3).fit(X)
features_df['cluster'] = kmeans.labels_
return features_df
8.3 实时听歌分析
结合WebSocket实现实时监控:
python复制from flask_socketio import SocketIO
socketio = SocketIO(app)
@socketio.on('update')
def handle_update():
while True:
new_data = get_recent_tracks(limit=1)
socketio.emit('new_track', new_data.to_dict())
time.sleep(30)
这个项目最让我惊喜的是发现了自己听歌习惯中的一些模式,比如周三下午倾向于听高能量音乐,而周末早晨则偏好柔和的爵士乐。通过定期分析,我不仅更好地理解了自己的音乐品味,还发现了许多符合这些模式的新歌。
