Python实战:抓取与可视化音乐榜单数据,分析歌曲热度趋势
最近在分析音乐榜单数据时发现很多朋友对一首歌的全球热度变化趋势很感兴趣尤其是像 Olivia Rodrigo 的《Good 4 u》这样的现象级单曲。它不仅在 Spotify 全球日榜上掀起波澜更在 Billboard Hot 100 榜单上上演了一场精彩的“位次推移”大戏。本文将带你从零开始完整复现如何获取、处理并可视化这类榜单数据最终生成一张清晰展示歌曲排名随时间变化的推移图。无论你是数据爱好者、音乐行业从业者还是想学习 Python 数据分析的开发者都能从这篇实战教程中获得一套可直接复用的代码和方法。1. 项目背景与核心概念在音乐流媒体时代一首歌的成功与否其在不同榜单上的排名变化是最直观的衡量标准之一。我们常听到“空降冠军”、“逆袭回升”、“高位徘徊”等说法这些词汇描述的正是歌曲的“位次推移”Chart Movement。Billboard Hot 100美国乃至全球最具权威性的单曲排行榜综合了实体销量、数字下载、电台点播和流媒体播放量包括 Spotify、Apple Music 等数据。一首歌在 Hot 100 上的排名变化反映了其在美国市场的综合热度走势。Spotify 全球日榜代表了全球最大的音乐流媒体平台每日的播放量排名是观察歌曲即时、全球性流媒体热度的绝佳窗口。其数据波动往往更加频繁和剧烈。位次推移分析通过追踪一首歌在不同榜单上每日或每周的排名绘制出其排名随时间变化的折线图。上升曲线代表热度攀升下降曲线则代表热度减退。对比不同榜单的曲线可以分析歌曲在不同市场或数据维度如流媒体 vs 综合热度的表现差异。本次实战我们将以 Olivia Rodrigo 的《Good 4 u》为例目标是获取其在某一段时间内例如发歌后两个月的 Spotify 全球日榜和 Billboard Hot 100 周榜排名数据并进行可视化分析。2. 环境准备与工具说明本项目主要使用 Python 进行数据抓取、处理和可视化。请确保你的开发环境已就绪。核心工具与库编程语言Python 3.8 及以上版本。开发环境推荐使用 Jupyter Notebook 或 VS Code 进行交互式开发和调试。关键库requests/selenium用于从网站抓取爬取榜单数据。requests适用于静态页面selenium适用于需要 JavaScript 渲染的动态页面。pandas数据处理和分析的核心库用于清洗、整合和操作数据表格。matplotlibseaborn数据可视化库用于绘制精美的位次推移图。BeautifulSoup4/lxmlHTML 解析库配合requests使用来提取网页中的特定数据。数据来源声明请注意直接抓取 Billboard 或 Spotify 官方数据可能违反其服务条款。为了教学目的我们将使用公开的、允许访问的榜单数据存档网站如kworb.net或模拟手动查找公开数据集的方式进行。在实际应用中请务必遵守相关网站的使用条款考虑使用官方 API如 Spotify Web API或购买正规数据源。安装依赖打开终端或命令提示符执行以下命令安装必要的库pip install requests pandas matplotlib seaborn beautifulsoup4 lxml如果目标网站是动态加载的你可能还需要安装selenium和对应的 WebDriverpip install selenium # 同时需要下载 ChromeDriver 或 GeckoDriver 并配置到系统 PATH3. 数据获取策略与原理拆解获取准确的榜单历史数据是本项目的第一步也是最具挑战性的一环。主要有以下几种思路3.1 思路一从聚合数据网站抓取以 kworb.net 为例kworb.net是一个知名的音乐数据聚合网站它整理了 Billboard、Spotify、iTunes 等平台的历史榜单数据并以结构化的表格形式呈现非常适合爬虫初学者。工作原理分析页面结构使用浏览器开发者工具F12查看目标页面的 HTML 结构。例如查找https://kworb.net/spotify/artist/1McMsnEElThX1knmY4oliG.htmlOlivia Rodrigo 的 Spotify 页面或特定歌曲的榜单详情页。定位数据表格榜单数据通常存放在table标签内。我们需要找到这个表格的 HTML 标识如id或class。发送HTTP请求使用requests.get()获取网页的 HTML 源代码。解析与提取使用BeautifulSoup解析 HTML定位到目标表格然后用pandas的read_html()函数直接将表格转换为 DataFrame或者手动遍历表格行tr和单元格td提取数据。优点数据集中易于解析免去了处理复杂 API 的麻烦。缺点依赖第三方网站其数据更新频率和准确性无法绝对保证需遵守该网站的robots.txt协议。3.2 思路二使用官方API推荐用于生产环境Spotify Web API提供了丰富的端点来获取艺术家、专辑、歌曲的详细信息但不直接提供历史日榜排名。你可以获取歌曲的当前流行度指数popularity0-100但这不是排名。历史流媒体数据可能需要商业权限。Billboard APIBillboard 官方有提供部分数据的 API但通常也是商业接口。对于个人学习和非商业用途直接爬取官网历史榜单页面是更常见的做法需谨慎评估法律风险。鉴于教学和可操作性下文将主要基于思路一kworb.net进行演示并强调数据获取的伦理和技术细节。4. 完整实战案例获取与可视化《Good 4 u》排名数据我们将流程分解为数据抓取、数据清洗、数据整合、可视化四个步骤。4.1 步骤一抓取 Spotify 全球日榜排名模拟假设我们在kworb.net上找到了《Good 4 u》的 Spotify 流媒体历史页面URL 需实际查找。这里我们模拟一个抓取过程。import requests from bs4 import BeautifulSoup import pandas as pd import time # 目标URL示例实际URL需要你根据网站结构寻找 # 假设结构为https://kworb.net/spotify/song/xxxxx.html song_id “6RUKPb4LETWmmr3iAEQktW” # Good 4 u 的Spotify ID (示例非真实) url f“https://kworb.net/spotify/song/{song_id}.html” headers { ‘User-Agent’: ‘Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36’ # 模拟浏览器访问 } try: response requests.get(url, headersheaders) response.raise_for_status() # 检查请求是否成功 soup BeautifulSoup(response.content, ‘html.parser’) # 假设日榜数据在第一个表格里我们需要根据实际页面调整选择器 # 使用浏览器开发者工具精确找到表格的id或class table soup.find(‘table’, {‘class’: ‘wikitable’}) # 示例classkworb常用 if table: # 使用pandas直接读取HTML表格 df_list pd.read_html(str(table)) spotify_df df_list[0] # 假设第一个表格是我们需要的 print(“Spotify 数据抓取成功前5行”) print(spotify_df.head()) else: print(“未找到榜单表格请检查页面结构或选择器。”) # 可以尝试其他选择器如 soup.find_all(‘table’)[1] except requests.exceptions.RequestException as e: print(f“网络请求出错{e}”) except Exception as e: print(f“解析过程出错{e}”) # 为了演示我们创建一份模拟的Spotify全球日榜数据2023年某两周 import numpy as np dates pd.date_range(‘2023-05-01’, periods14, freq‘D’) # 假设从5月1日开始 # 模拟排名初期高位随后下降中期有小幅回升 spotify_ranks [1, 1, 2, 3, 5, 8, 12, 15, 10, 8, 12, 18, 22, 25] spotify_daily_data pd.DataFrame({ ‘Date’: dates, ‘Platform’: ‘Spotify Global’, ‘Rank’: spotify_ranks }) print(“\n模拟的 Spotify 全球日榜数据”) print(spotify_daily_data)4.2 步骤二抓取 Billboard Hot 100 周榜排名模拟Billboard Hot 100 是周榜数据频率与日榜不同。我们同样模拟抓取过程。# 模拟从 Billboard 或 kworb 抓取 Hot 100 周榜数据 # 假设URL格式https://kworb.net/bb/artist/oliviarodrigo.html 或歌曲特定页面 # 创建模拟的Billboard Hot 100周榜数据同一时间段周榜 # 周榜日期通常是每周六更新 billboard_dates pd.date_range(‘2023-05-06’, periods4, freq‘7D’) # 5月6日13日20日27日 # 模拟排名空降冠军随后位次变化 billboard_ranks [1, 1, 2, 4] billboard_weekly_data pd.DataFrame({ ‘Date’: billboard_dates, ‘Platform’: ‘Billboard Hot 100’, ‘Rank’: billboard_ranks }) print(“\n模拟的 Billboard Hot 100 周榜数据”) print(billboard_weekly_data)4.3 步骤三数据清洗与整合将两个来源的数据合并并统一格式为绘图做准备。# 合并两个数据集 combined_data pd.concat([spotify_daily_data, billboard_weekly_data], ignore_indexTrue) # 确保日期列是 datetime 类型 combined_data[‘Date’] pd.to_datetime(combined_data[‘Date’]) # 按平台和日期排序 combined_data combined_data.sort_values([‘Platform’, ‘Date’]).reset_index(dropTrue) # 检查数据 print(“\n合并后的数据”) print(combined_data) print(f“\n数据概览”) print(combined_data.info()) print(combined_data[‘Platform’].value_counts())4.4 步骤四绘制位次推移图使用matplotlib和seaborn绘制双线折线图直观展示排名变化。import matplotlib.pyplot as plt import seaborn as sns # 设置中文字体和图表样式如果不需要中文可省略字体设置 # plt.rcParams[‘font.sans-serif’] [‘SimHei’, ‘Arial’] # 用来正常显示中文标签 # plt.rcParams[‘axes.unicode_minus’] False # 用来正常显示负号 sns.set_style(“whitegrid”) # 设置seaborn风格 plt.figure(figsize(14, 8)) # 设置画布大小 # 为每个平台绘制折线 platforms combined_data[‘Platform’].unique() colors {‘Spotify Global’: ‘#1DB954’, ‘Billboard Hot 100’: ‘#FF6B6B’} # Spotify绿Billboard红 markers {‘Spotify Global’: ‘o’, ‘Billboard Hot 100’: ‘s’} # 圆圈和方块 for platform in platforms: platform_data combined_data[combined_data[‘Platform’] platform] plt.plot(platform_data[‘Date’], platform_data[‘Rank’], labelplatform, colorcolors.get(platform, ‘blue’), markermarkers.get(platform, ‘o’), linewidth2.5, markersize8) # 优化图表细节 plt.gca().invert_yaxis() # 反转Y轴让排名1在顶部更符合阅读习惯 plt.title(‘Olivia Rodrigo - “Good 4 u” 位次推移图\nSpotify全球日榜 vs Billboard Hot 100周榜’, fontsize16, fontweight‘bold’, pad20) plt.xlabel(‘日期’, fontsize12) plt.ylabel(‘排名 (数字越小越靠前)’, fontsize12) plt.legend(title‘榜单平台’, fontsize11, title_fontsize12) plt.grid(True, which‘both’, linestyle‘—’, linewidth0.5, alpha0.7) # 美化X轴日期格式 plt.gcf().autofmt_xdate() # 自动倾斜日期标签 # 添加数据标签可选数据点多时可能拥挤 # for platform in platforms: # platform_data combined_data[combined_data[‘Platform’] platform] # for x, y in zip(platform_data[‘Date’], platform_data[‘Rank’]): # plt.text(x, y0.5, f’{int(y)}’, ha‘center’, va‘bottom’, fontsize9, colorcolors.get(platform)) plt.tight_layout() # 自动调整子图参数使之填充整个图像区域 plt.show()预期结果你将得到一张折线图。X轴是时间Y轴是排名顶部为第1名。绿色折线带圆圈标记代表 Spotify 全球日榜每日一个点波动可能更频繁。红色折线带方块标记代表 Billboard Hot 100 周榜每周一个点趋势相对平滑。通过对比你可以清晰看到歌曲发布初期在两个榜单均迅速登顶。Spotify 日榜排名可能因流媒体日活变化而更快出现下滑和波动。Billboard 周榜因综合了销量、电台等数据排名下降可能相对缓慢体现了更持久的综合热度。5. 常见问题与排查思路在实践过程中你可能会遇到以下问题问题现象可能原因解决思路requests.get()返回 403 或 404 错误1. 网站有反爬机制如验证 User-Agent。2. 页面需要登录或 JavaScript 加载。3. URL 已失效或拼写错误。1. 检查并完善headers模拟真实浏览器。2. 尝试使用selenium处理动态页面。3. 手动在浏览器中访问该 URL 确认有效性。BeautifulSoup找不到表格 (find返回None)1. HTML 结构判断错误表格的class或id不对。2. 数据可能是通过 JS 异步加载初始 HTML 中没有。1. 使用开发者工具仔细检查元素尝试soup.find_all(‘table’)查看所有表格。2. 使用selenium等待页面完全加载后再获取page_source。pd.read_html()解析出错或返回空列表1. 表格结构复杂pandas无法自动识别。2. 网页编码问题。1. 改用BeautifulSoup手动解析表格行 (tr) 和单元格 (td)。2. 指定encoding参数如response.content.decode(‘utf-8’)。图表Y轴方向不符合习惯排名1在底部默认坐标系排名值越大位置越高。使用plt.gca().invert_yaxis()反转Y轴。两条曲线看起来不协调一个点密一个点疏数据频率不同日榜 vs 周榜。这是正常现象正好反映了不同榜单的更新频率。可以在图例或标题中说明。数据抓取速度慢或被封IP高频请求触发了网站的反爬虫策略。1. 在请求间添加随机延时time.sleep(random.uniform(1, 3))。2. 使用代理IP池高级。最重要尊重robots.txt控制抓取频率仅用于个人学习。6. 最佳实践与工程建议遵守法律法规与道德规范优先使用官方API对于商业或长期项目尽一切可能申请和使用 Spotify、Billboard 等平台的官方 API。这是最稳定、合法的方式。尊重robots.txt在抓取任何网站前访问https://目标网站/robots.txt查看是否允许爬虫抓取目标路径。限制请求频率在代码中设置合理的延时如每秒1次请求避免对目标服务器造成负担。明确数据用途确保你的项目是用于个人学习、研究或教育而非商业盈利。在成果中注明数据来源。代码健壮性与可维护性异常处理如示例所示使用try-except块包裹网络请求和解析代码确保单次失败不会导致整个程序崩溃。配置化将 URL、请求头、文件保存路径等变量提取到配置文件或脚本开头方便修改。数据持久化抓取到的数据应立即保存到本地文件如 CSV、JSON 或 SQLite 数据库避免每次分析都重新抓取。# 保存数据 combined_data.to_csv(‘good4u_chart_history.csv’, indexFalse, encoding‘utf-8-sig’) # 读取数据 df pd.read_csv(‘good4u_chart_history.csv’, parse_dates[‘Date’])函数封装将数据抓取、清洗、绘图的代码分别封装成函数提高代码复用性。数据分析深度拓展计算在榜周数统计歌曲在 Top 10、Top 50、Top 100 内停留的周数/天数。计算排名变化幅度计算每周或每日的排名升降名次。多歌曲对比在同一张图中绘制多位歌手或歌曲的排名曲线进行横向对比。关联其他数据尝试寻找或抓取社交媒体讨论热度、音乐视频播放量等数据与榜单排名做相关性分析。可视化优化关键节点标注在曲线上标注重要事件点如“音乐视频发布”、“电台大力推广”、“获奖”等分析事件对排名的影响。使用渐变色用颜色深浅表示时间先后或排名高低。交互式图表考虑使用plotly库生成交互式图表可以悬停查看具体日期的排名数值。通过这个完整的项目你不仅学会了如何分析一首歌的榜单位次推移更掌握了一套从网页抓取、数据处理到可视化的通用数据分析流程。这套方法稍加修改就可以用于分析任何你感兴趣的榜单数据例如电影票房排名、应用商店排名、社交媒体热搜趋势等。数据就在那里关键在于如何获取并从中提炼出有价值的洞察。