作为一名长期关注音乐数据分析的Python开发者,我注意到市场上缺乏针对网易云音乐排行榜的轻量级分析工具。现有的解决方案要么功能过于简单,要么需要付费使用。这促使我开发了这套开源的网易云排行榜数据分析系统,旨在为音乐爱好者、行业从业者和研究者提供一个免费且强大的数据分析平台。
这个系统的核心价值在于:
系统采用典型的数据处理流水线架构,分为五个核心层次:
这种分层设计使得系统各模块职责明确,便于后期维护和功能扩展。
在技术选型上,我主要基于以下考虑:
提示:在实际开发中发现,网易云音乐对爬虫有一定反制措施,建议设置合理的请求间隔(建议0.5-1秒)并使用随机User-Agent。
数据采集是整个系统的基础,我设计了多层次的采集策略:
python复制def fetch_rank_data(rank_type, date=None):
"""
获取指定类型的排行榜数据
:param rank_type: 榜单类型(hot/new/original)
:param date: 指定日期(默认为当天)
:return: 榜单数据DataFrame
"""
base_url = "https://music.163.com/discover/toplist"
headers = {
'User-Agent': get_random_user_agent(),
'Referer': 'https://music.163.com/'
}
try:
# 使用Requests获取页面
response = requests.get(f"{base_url}?id={RANK_IDS[rank_type]}",
headers=headers)
response.raise_for_status()
# 使用BeautifulSoup解析
soup = BeautifulSoup(response.text, 'lxml')
items = soup.select('.m-table-rank tbody tr')
data = []
for item in items:
# 提取歌曲信息...
pass
return pd.DataFrame(data)
except Exception as e:
logger.error(f"获取{rank_type}榜单失败: {str(e)}")
return None
对于动态加载的内容,我使用Selenium进行模拟操作:
python复制def fetch_dynamic_data():
options = webdriver.ChromeOptions()
options.add_argument('--headless')
driver = webdriver.Chrome(options=options)
try:
driver.get("https://music.163.com/#/discover/toplist")
WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.CSS_SELECTOR, ".m-table-rank"))
)
# 获取动态渲染后的页面源码
page_source = driver.page_source
# 后续解析逻辑...
finally:
driver.quit()
采集到的原始数据需要经过严格清洗:
数据清洗流程:
特征工程:
热度 = 0.6*播放量 + 0.3*评论数 + 0.1*点赞数python复制def clean_data(raw_df):
"""数据清洗和特征工程"""
# 处理缺失值
raw_df['play_count'] = raw_df['play_count'].fillna(
raw_df.groupby('rank')['play_count'].transform('median'))
# 过滤异常值
q_high = raw_df['play_count'].quantile(0.99)
cleaned_df = raw_df[(raw_df['play_count'] > 0) &
(raw_df['play_count'] < q_high)].copy()
# 特征工程
cleaned_df['hot_score'] = 0.6*cleaned_df['play_count'] + \
0.3*cleaned_df['comment_count'] + \
0.1*cleaned_df['like_count']
return cleaned_df
趋势分析是系统的核心功能之一,我实现了以下几种分析方法:
单曲生命周期分析:
风格趋势分析:
python复制def analyze_trend(song_df):
"""分析单曲趋势"""
result = {
'max_rank': song_df['rank'].min(),
'min_rank': song_df['rank'].max(),
'avg_rank': song_df['rank'].mean(),
'trend': None
}
# 使用线性回归判断总体趋势
X = np.arange(len(song_df)).reshape(-1, 1)
y = song_df['rank'].values
model = LinearRegression().fit(X, y)
result['trend'] = '上升' if model.coef_[0] < -0.5 else \
'下降' if model.coef_[0] > 0.5 else '平稳'
return result
对歌手的分析维度包括:
python复制def analyze_artist(artist_name, full_df):
"""分析歌手表现"""
artist_df = full_df[full_df['artist'] == artist_name]
if artist_df.empty:
return None
# 计算基础指标
result = {
'song_count': artist_df['song'].nunique(),
'avg_rank': artist_df.groupby('song')['rank'].mean().mean(),
'rank_std': artist_df.groupby('song')['rank'].std().mean(),
'best_song': artist_df.loc[artist_df['rank'].idxmin(), 'song']
}
return result
使用Matplotlib和Seaborn生成出版级质量的静态图表:
python复制def plot_rank_trend(song_df, song_name):
"""绘制单曲排名趋势图"""
plt.figure(figsize=(12, 6))
sns.lineplot(x='date', y='rank', data=song_df, marker='o')
plt.gca().invert_yaxis() # 排名越高数值越小
plt.title(f"'{song_name}'排名趋势", fontsize=14)
plt.xlabel('日期')
plt.ylabel('排名')
plt.grid(True, linestyle='--', alpha=0.6)
# 标注关键点
max_rank = song_df['rank'].min()
max_date = song_df.loc[song_df['rank'].idxmin(), 'date']
plt.annotate(f'最高排名:{max_rank}', xy=(max_date, max_rank),
xytext=(10, 10), textcoords='offset points',
arrowprops=dict(arrowstyle='->'))
return plt
使用Pyecharts创建丰富的交互式图表:
python复制def create_interactive_chart(data):
"""创建交互式排名变化图"""
chart = Line(init_opts=opts.InitOpts(width="100%", height="600px"))
# 添加X轴(日期)
dates = sorted(data['date'].unique())
chart.add_xaxis(list(dates))
# 为每首歌添加一条线
for song in data['song'].unique():
song_data = data[data['song'] == song]
chart.add_yaxis(
series_name=song,
y_axis=song_data['rank'].tolist(),
symbol_size=8,
label_opts=opts.LabelOpts(is_show=False),
linestyle_opts=opts.LineStyleOpts(width=2)
)
# 设置全局配置
chart.set_global_opts(
title_opts=opts.TitleOpts(title="歌曲排名变化趋势"),
tooltip_opts=opts.TooltipOpts(trigger="axis"),
yaxis_opts=opts.AxisOpts(
type_="value",
name="排名",
inverse=True,
axislabel_opts=opts.LabelOpts(formatter="{value}"),
splitline_opts=opts.SplitLineOpts(is_show=True)
),
datazoom_opts=[opts.DataZoomOpts(), opts.DataZoomOpts(type_="inside")],
legend_opts=opts.LegendOpts(
orient="vertical", pos_right="0%", pos_top="15%"
)
)
return chart
建议使用conda创建独立的Python环境:
bash复制conda create -n netease_analysis python=3.8
conda activate netease_analysis
pip install -r requirements.txt
requirements.txt包含的主要依赖:
code复制requests==2.26.0
beautifulsoup4==4.10.0
selenium==4.1.0
pandas==1.3.4
numpy==1.21.4
matplotlib==3.5.0
seaborn==0.11.2
pyecharts==1.9.1
数据采集:
bash复制python crawler.py --rank hot --days 30
数据分析:
bash复制python analyzer.py --task trend --output results/trend.png
启动可视化面板:
bash复制python app.py
注意:首次运行前需要下载ChromeDriver,版本需与本地Chrome浏览器匹配。
通过分析新歌的上榜速度和排名提升幅度,可以识别出有潜力成为爆款的歌曲。例如,某歌曲在3天内从第95名升至第12名,这种快速上升的歌曲往往会在接下来几天进入前十。
某新人歌手在三个月内:
这些数据表明该歌手正处于快速成长期,值得行业关注。
分析2023年数据发现:
这些趋势对音乐人的创作方向和唱片公司的企划策略具有参考价值。
在实际开发过程中,最大的挑战是网易云音乐反爬策略的不断升级。通过持续观察和调整采集策略,最终实现了稳定可靠的数据采集方案。对于数据分析部分,特征工程的质量直接决定了后续分析的深度,需要不断迭代优化。