1. 项目概述:Python与Spotify数据分析
作为一名长期使用Python进行数据分析的开发者,我发现音乐流媒体数据蕴含着丰富的个人听歌习惯信息。Spotify作为全球最大的音乐平台之一,不仅提供了海量音乐资源,还通过完善的API开放了用户听歌数据。本文将分享如何用Python获取并分析你的Spotify听歌记录,揭示那些你可能从未注意到的音乐偏好模式。
这个项目适合:
- 想了解自己音乐品味的普通用户
- 希望练习Python数据分析的数据科学初学者
- 需要处理音乐相关数据的开发者
通过本文,你将学会:
- 使用Spotify API获取个人听歌数据
- 用Python进行数据清洗和预处理
- 分析听歌时间、艺人偏好等维度
- 可视化展示分析结果
2. 环境准备与API配置
2.1 创建Spotify开发者应用
首先需要访问Spotify开发者仪表板(https://developer.spotify.com/dashboard/)创建一个应用:
- 登录你的Spotify账号
- 点击"创建应用"按钮
- 填写应用名称和描述(如"My Listening Analysis")
- 创建完成后记录下Client ID和Client Secret
注意:Client Secret是敏感信息,切勿直接暴露在代码中或上传到公开仓库。
2.2 安装必要的Python库
我们将使用以下Python库:
spotipy:Spotify官方API封装库pandas:数据处理和分析matplotlib/seaborn:数据可视化python-dotenv:管理环境变量
安装命令:
bash复制pip install spotipy pandas matplotlib seaborn python-dotenv
2.3 配置认证信息
创建一个.env文件存储认证信息:
env复制SPOTIPY_CLIENT_ID='your_client_id'
SPOTIPY_CLIENT_SECRET='your_client_secret'
SPOTIPY_REDIRECT_URI='http://localhost:8888/callback'
然后在Python中加载这些配置:
python复制from dotenv import load_dotenv
import os
load_dotenv()
client_id = os.getenv('SPOTIPY_CLIENT_ID')
client_secret = os.getenv('SPOTIPY_CLIENT_SECRET')
redirect_uri = os.getenv('SPOTIPY_REDIRECT_URI')
3. 获取听歌数据
3.1 初始化Spotipy客户端
python复制import spotipy
from spotipy.oauth2 import SpotifyOAuth
# 设置访问范围
scope = "user-library-read user-read-recently-played user-top-read"
# 创建认证对象
sp = spotipy.Spotify(auth_manager=SpotifyOAuth(
client_id=client_id,
client_secret=client_secret,
redirect_uri=redirect_uri,
scope=scope))
3.2 获取最近播放的歌曲
python复制# 获取最近50首播放的歌曲
recently_played = sp.current_user_recently_played(limit=50)
# 解析数据
recent_tracks = []
for item in recently_played['items']:
track = item['track']
played_at = item['played_at']
recent_tracks.append({
'name': track['name'],
'artist': track['artists'][0]['name'],
'album': track['album']['name'],
'duration_ms': track['duration_ms'],
'played_at': played_at,
'popularity': track['popularity']
})
3.3 获取最常听的艺人
python复制# 获取长期最常听的艺人
top_artists = sp.current_user_top_artists(time_range='long_term', limit=20)
artist_data = []
for artist in top_artists['items']:
artist_data.append({
'name': artist['name'],
'genres': artist['genres'],
'popularity': artist['popularity'],
'followers': artist['followers']['total']
})
4. 数据分析与处理
4.1 数据清洗与转换
将获取的数据转换为pandas DataFrame以便分析:
python复制import pandas as pd
from datetime import datetime
# 转换听歌记录
df_tracks = pd.DataFrame(recent_tracks)
df_tracks['played_at'] = pd.to_datetime(df_tracks['played_at'])
df_tracks['duration_min'] = df_tracks['duration_ms'] / 60000
df_tracks['hour_played'] = df_tracks['played_at'].dt.hour
# 转换艺人数据
df_artists = pd.DataFrame(artist_data)
df_artists['genres'] = df_artists['genres'].apply(lambda x: ', '.join(x))
4.2 听歌时间分析
python复制# 按小时统计听歌频率
hourly_plays = df_tracks.groupby('hour_played').size().reset_index(name='count')
# 计算平均听歌时长
avg_duration = df_tracks['duration_min'].mean()
4.3 艺人偏好分析
python复制# 统计最常听艺人
top_artists_count = df_tracks['artist'].value_counts().head(10)
# 艺人流派分布
genre_counts = pd.Series(
[genre for sublist in df_artists['genres'].str.split(', ')
for genre in sublist]).value_counts()
5. 数据可视化
5.1 听歌时间分布
python复制import matplotlib.pyplot as plt
import seaborn as sns
plt.figure(figsize=(12, 6))
sns.barplot(x='hour_played', y='count', data=hourly_plays, palette='viridis')
plt.title('听歌时间分布(按小时)')
plt.xlabel('小时')
plt.ylabel('播放次数')
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()
5.2 最常听艺人可视化
python复制plt.figure(figsize=(12, 8))
top_artists_count.plot(kind='barh', color='skyblue')
plt.title('最常听艺人Top 10')
plt.xlabel('播放次数')
plt.ylabel('艺人名称')
plt.gca().invert_yaxis()
plt.show()
5.3 歌曲时长分布
python复制plt.figure(figsize=(10, 6))
sns.histplot(df_tracks['duration_min'], bins=20, kde=True, color='purple')
plt.title('歌曲时长分布')
plt.xlabel('时长(分钟)')
plt.ylabel('歌曲数量')
plt.axvline(avg_duration, color='red', linestyle='--',
label=f'平均时长: {avg_duration:.1f}分钟')
plt.legend()
plt.show()
6. 高级分析与见解
6.1 音乐特征分析
Spotify为每首歌曲提供了音频特征数据,我们可以获取这些数据进行更深入的分析:
python复制# 获取歌曲ID列表
track_ids = df_tracks.index.tolist()
# 获取音频特征
audio_features = sp.audio_features(track_ids)
df_features = pd.DataFrame(audio_features)
# 合并数据
df_full = pd.concat([df_tracks.reset_index(drop=True),
df_features], axis=1)
6.2 情绪分析
根据音频特征分析歌曲情绪:
python复制# 计算情绪得分(基于能量和效价)
df_full['mood_score'] = (df_full['energy'] + df_full['valence']) / 2
# 分类情绪
df_full['mood'] = pd.cut(df_full['mood_score'],
bins=[0, 0.3, 0.7, 1],
labels=['平静', '中性', '兴奋'])
6.3 听歌情绪时间分布
python复制plt.figure(figsize=(12, 6))
sns.countplot(x='hour_played', hue='mood', data=df_full,
palette={'平静': 'blue', '中性': 'green', '兴奋': 'red'})
plt.title('不同时间段听歌情绪分布')
plt.xlabel('小时')
plt.ylabel('歌曲数量')
plt.legend(title='情绪')
plt.show()
7. 项目扩展与优化
7.1 定期自动收集数据
可以设置定时任务每天收集听歌数据:
python复制import schedule
import time
def collect_data():
# 收集数据的代码
pass
# 每天凌晨1点执行
schedule.every().day.at("01:00").do(collect_data)
while True:
schedule.run_pending()
time.sleep(60)
7.2 构建交互式仪表盘
使用Plotly Dash构建交互式可视化:
python复制import dash
from dash import dcc, html
import plotly.express as px
app = dash.Dash(__name__)
app.layout = html.Div([
dcc.Graph(figure=px.bar(hourly_plays, x='hour_played', y='count',
title='听歌时间分布')),
dcc.Graph(figure=px.pie(top_artists_count,
values=top_artists_count.values,
names=top_artists_count.index,
title='艺人分布'))
])
if __name__ == '__main__':
app.run_server(debug=True)
7.3 音乐推荐系统
基于分析结果构建简单的推荐系统:
python复制def recommend_similar_tracks(track_id, limit=5):
recommendations = sp.recommendations(seed_tracks=[track_id], limit=limit)
return [track['name'] for track in recommendations['tracks']]
# 示例:推荐与最近听的歌曲相似的歌曲
last_track_id = df_tracks.iloc[0]['id']
print(recommend_similar_tracks(last_track_id))
8. 常见问题与解决方案
8.1 认证失败问题
问题:获取访问令牌时返回"invalid_client"错误
解决方案:
- 检查Client ID和Client Secret是否正确
- 确保在Spotify开发者仪表板设置了正确的重定向URI
- 确认应用状态为"Active"
8.2 数据限制问题
问题:API返回的数据量不足
解决方案:
- 使用分页参数获取更多数据:
python复制results = sp.current_user_recently_played(limit=50, after=timestamp)
- 定期收集数据建立历史数据库
8.3 性能优化
问题:处理大量数据时速度慢
解决方案:
- 使用多线程获取数据:
python复制from concurrent.futures import ThreadPoolExecutor
def fetch_track_features(track_id):
return sp.audio_features(track_id)[0]
with ThreadPoolExecutor(max_workers=5) as executor:
features = list(executor.map(fetch_track_features, track_ids))
- 使用缓存减少API调用
9. 实际应用中的经验分享
在完成多个类似项目后,我总结出以下几点实用经验:
-
数据收集策略:不要一次性获取所有数据,而是建立增量收集机制。Spotify API有速率限制(每分钟约300次请求),合理规划请求频率很重要。
-
错误处理:网络请求难免会遇到超时或失败,实现自动重试机制:
python复制from tenacity import retry, stop_after_attempt, wait_exponential
@retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=4, max=10))
def safe_api_call(func, *args, **kwargs):
return func(*args, **kwargs)
- 数据存储:考虑使用SQLite或小型数据库存储历史数据,而不是每次都从API获取。我通常使用这样的结构:
python复制import sqlite3
conn = sqlite3.connect('spotify_data.db')
df_tracks.to_sql('recent_tracks', conn, if_exists='append', index=False)
- 分析维度扩展:除了基础分析,还可以考虑:
- 每周/每月的听歌模式变化
- 新发现艺人占比(首次出现的艺人)
- 歌曲重复收听率
- 根据季节/天气的外部数据分析
- 可视化优化:静态图表虽然简单,但交互式可视化能提供更好体验。我推荐:
- Plotly/Dash:适合构建完整仪表盘
- Altair:声明式语法,快速生成交互图表
- Streamlit:快速构建数据应用
这个项目最有趣的部分是发现自己的听歌习惯中那些不为人知的模式。比如,我发现自己周三下午倾向于听更激烈的音乐,而周末早晨则偏好柔和的爵士乐。这些洞察不仅有趣,还能帮助我们更好地理解自己的情绪和行为模式。