从数据采集到API构建:Python实战打造主题音乐数据集

Python数据采集音频处理
于 2026-08-03 04:11:18 修改
·本内容遵循CC 4.0 BY-SA版权协议

最近在技术社区看到一个很有意思的现象:很多开发者,尤其是后端和算法工程师,开始把“音乐”作为测试和演示数据源。这背后其实反映了一个普遍的技术痛点:如何快速、低成本地获取和处理一批高质量、有明确情感标签的音频数据?

你可能遇到过这些场景:

  • 想测试一下新上线的语音识别或情感分析API,手头只有几个干巴巴的测试音频,覆盖不了复杂场景。
  • 在做一个内容推荐或情绪感知的Demo,需要一批带有“伤感”、“欢快”、“平静”等标签的音乐来训练或验证模型,但自己整理费时费力。
  • 想研究音频特征提取或音乐信息检索(MIR),但公开数据集要么太大(如百万首的MagnaTagATune),要么太学术化,只想快速有个直观感受。

这时候,一个现成的、主题明确的音乐合集,比如一个“伤感音乐合集”,其技术价值就凸显出来了。它不再仅仅是歌单,而是一个即拿即用的、带有强上下文语义的音频数据集。本文就将以构建一个“伤感音乐合集”为例,拆解背后的完整技术链路:从数据源的合法获取、元信息(如歌名、歌手)的抓取与清洗,到音频文件的下载、标签化组织,最后到基于这个数据集的一个简单应用演示。

你会发现,这件事的核心不是“下载音乐”,而是一套标准的数据工程流水线。我们将用Python作为主要工具,贯穿始终。

1. 为什么技术人需要关注“主题音乐合集”?

在开始敲代码之前,有必要先厘清思路。对于开发者而言,处理一个“伤感音乐合集”项目,真正的目标通常不是那几首歌,而是以下几个技术能力的实践或需求的满足:

  1. 数据采集与爬虫实践:如何从公开、合法的信息源(如音乐平台的公开歌单页面)结构化地获取音乐信息?这涉及到HTTP请求、HTML解析、反爬策略应对等经典爬虫问题。
  2. 数据清洗与结构化:爬取的原始数据往往是杂乱无章的。如何清洗歌名、歌手、专辑信息?如何处理乱码、去除无效条目?最终如何存储为结构化的格式(如CSV、JSON)或直接写入数据库?
  3. 媒体资源获取与处理:如何根据元数据,通过合法途径获取对应的音频文件?这里需要严格区分版权边界。我们通常寻找可免费下载的合法音源,或使用低质量预览片段用于技术测试。同时,可能涉及音频格式转换、采样率统一等预处理步骤。
  4. 标签化与元数据管理:“伤感”是一个主观标签。如何为这个合集建立有效的元数据体系?除了手动标注,能否利用音频特征(如频谱、节奏)或歌词情感分析进行辅助分类?这引出了音乐信息检索(MIR)的初级应用。
  5. 应用接口构建:整理好的合集如何被其他程序使用?我们可以构建一个简单的REST API或本地库,提供按歌手、歌名、情感强度等条件的查询和播放功能。

本文将聚焦于前三个核心环节,并给出第四个环节的思路,为你呈现一个完整、可落地的技术项目。

2. 核心概念与技术栈选择

在动手前,我们先明确几个关键概念和工具选择。

2.1 关键概念

  • 元数据(Metadata):指描述音乐本身的数据,如标题艺术家专辑时长发行年份风格标签(如伤感)。这是我们爬取和清洗的主要对象。
  • 音频特征(Audio Features):通过算法从音频信号中提取的量化指标,例如节奏(Tempo)调性(Key)响度(Loudness)频谱质心(Spectral Centroid)等。这些特征可以用于客观地辅助“伤感”等主观情感的判断。
  • 音乐信息检索(Music Information Retrieval, MIR):一个跨学科领域,研究如何从音乐中提取信息。我们项目中的“情感分类”就是MIR的一个子任务。
  • 数据流水线(Data Pipeline):指数据从采集、清洗、处理到存储/应用的一系列自动化步骤。一个健壮的流水线是项目可复现、可扩展的关键。

2.2 技术栈选择

我们选择Python,因为它拥有极其丰富的库来支持上述每一个环节。

环节 推荐库 用途
数据采集 requests, httpx, aiohttp (异步) 发送HTTP请求,获取网页源码。
BeautifulSoup4, lxml, parsel 解析HTML/XML,提取结构化数据。
Selenium, Playwright 处理JavaScript动态渲染的页面。
数据清洗与存储 pandas 数据清洗、分析和存储的核心。
json, csv (标准库) 序列化存储数据。
SQLAlchemy 如果需要存入数据库(如SQLite)。
音频处理 youtube-dl, yt-dlp 从支持的平台下载音频(务必遵守平台条款)。
pydub, librosa 音频文件格式转换、剪切、特征提取。
mutagen 读取和写入音频文件的元数据标签(如ID3)。
应用与可视化 Flask / FastAPI 快速构建查询API。
matplotlib, seaborn 可视化音频特征或数据分析结果。

重要声明:本文所有技术和代码示例,仅用于学习数据采集、清洗和处理的技术原理。在实际操作中,你必须:

  1. 严格遵守目标网站的robots.txt协议。
  2. 尊重版权,仅获取用于个人学习、研究的公开信息或合法授权内容。
  3. 控制请求频率,避免对目标服务器造成压力。
  4. 绝不将获取的数据用于任何商业用途

3. 环境准备与依赖安装

我们创建一个干净的Python虚拟环境来管理依赖。

BASH
# 1. 创建项目目录并进入
mkdir sentimental_music_collection && cd sentimental_music_collection
 
# 2. 创建虚拟环境 (以Python3.8+为例)
python3 -m venv venv
 
# 3. 激活虚拟环境
# Linux/macOS
source venv/bin/activate
# Windows
# venv\Scripts\activate
 
# 4. 安装核心依赖
pip install requests beautifulsoup4 pandas yt-dlp pydub
 
# 可选:安装异步爬虫、特征提取等库
# pip install aiohttp librosa flask

创建项目结构:

TEXT
sentimental_music_collection/
├── scraper/ # 爬虫模块
│ ├── __init__.py
│ └── music_meta_spider.py
├── downloader/ # 下载器模块
│ ├── __init__.py
│ └── audio_downloader.py
├── data/ # 数据目录
│ ├── raw/ # 原始数据
│ ├── processed/ # 清洗后数据
│ └── audio/ # 音频文件(注意.gitignore)
├── utils/ # 工具函数
│ ├── __init__.py
│ └── audio_processor.py
├── config.py # 配置文件
├── main.py # 主流程脚本
└── requirements.txt # 依赖列表

生成requirements.txt:

BASH
pip freeze > requirements.txt

4. 第一步:音乐元数据采集与清洗

我们假设从一个模拟的公开音乐榜单或歌单页面获取数据。在实际项目中,请替换为合法的数据源。

4.1 编写爬虫脚本

我们创建一个简单的爬虫来演示流程。这里以爬取一个静态页面为例。

PYTHON
# file: scraper/music_meta_spider.py
import requests
from bs4 import BeautifulSoup
import pandas as pd
import time
import logging
from typing import List, Dict
import re
 
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s: %(message)s')
 
class MusicMetaSpider:
"""音乐元数据爬虫示例类"""
def __init__(self, base_url: str, headers: Dict = None):
self.base_url = base_url
self.headers = headers or {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
}
self.session = requests.Session()
self.session.headers.update(self.headers)
def fetch_page(self, url: str) -> str:
"""获取页面内容"""
try:
resp = self.session.get(url, timeout=10)
resp.raise_for_status() # 检查HTTP错误
# 可以在这里处理编码问题
resp.encoding = resp.apparent_encoding
return resp.text
except requests.RequestException as e:
logging.error(f"请求失败: {url}, 错误: {e}")
return ""
def parse_music_list(self, html: str) -> List[Dict]:
"""解析音乐列表页面,提取元数据"""
soup = BeautifulSoup(html, 'lxml')
music_items = []
# 假设页面中音乐信息在 class='music-item' 的div中
# 这是一个示例选择器,实际需要根据目标网站结构调整
items = soup.select('.music-item')
for item in items:
try:
# 示例解析逻辑
title_elem = item.select_one('.title a')
artist_elem = item.select_one('.artist')
album_elem = item.select_one('.album')
# 时长可能藏在属性里或文本中
duration_elem = item.select_one('.duration')
title = title_elem.get_text(strip=True) if title_elem else "Unknown"
# 清洗歌名,去除多余空格和特殊符号
title = re.sub(r'\s+', ' ', title).strip()
artist = artist_elem.get_text(strip=True) if artist_elem else "Various Artists"
album = album_elem.get_text(strip=True) if album_elem else ""
duration = duration_elem.get_text(strip=True) if duration_elem else "0:00"
# 将时长字符串转换为秒数,便于后续处理
duration_sec = self._parse_duration(duration)
music_info = {
'title': title,
'artist': artist,
'album': album,
'duration_str': duration,
'duration_sec': duration_sec,
'source_url': title_elem.get('href', '') if title_elem else '',
'tags': ['sentimental'] # 手动添加标签,后续可扩展
}
music_items.append(music_info)
logging.debug(f"解析到歌曲: {title} - {artist}")
except Exception as e:
logging.warning(f"解析单个项目失败: {e}")
continue
return music_items
def _parse_duration(self, duration_str: str) -> int:
"""将 'MM:SS' 或 'HH:MM:SS' 格式的时长转换为秒"""
parts = duration_str.split(':')
try:
if len(parts) == 3: # HH:MM:SS
h, m, s = map(int, parts)
return h * 3600 + m * 60 + s
elif len(parts) == 2: # MM:SS
m, s = map(int, parts)
return m * 60 + s
else:
return 0
except ValueError:
return 0
def run(self, save_path: str = '../data/raw/music_list.csv'):
"""运行爬虫,保存数据"""
html = self.fetch_page(self.base_url)
if not html:
logging.error("未能获取页面内容,退出")
return
music_list = self.parse_music_list(html)
logging.info(f"共解析到 {len(music_list)} 首歌曲")
# 使用pandas保存为CSV
df = pd.DataFrame(music_list)
df.to_csv(save_path, index=False, encoding='utf-8-sig') # utf-8-sig 兼容Excel
logging.info(f"数据已保存至: {save_path}")
return df
 
# 示例用法
if __name__ == '__main__':
# !!! 重要:此处URL仅为示例,请替换为合法的、允许爬取的公开信息源 !!!
# 例如,可以找一些公开的、无版权音乐库的列表页,或者使用模拟数据。
EXAMPLE_URL = "https://example-music-site.com/sentimental-playlist"
spider = MusicMetaSpider(base_url=EXAMPLE_URL)
# 在实际运行前,我们先用模拟数据演示清洗步骤
print("爬虫类定义完成。实际运行时需配置合法URL。")

4.2 数据清洗与增强

由于直接爬取的数据可能不干净,我们需要进行清洗。

PYTHON
# file: main.py (部分功能)
import pandas as pd
import numpy as np
from pathlib import Path
 
def clean_and_enhance_data(raw_csv_path: str, output_csv_path: str):
"""清洗和增强音乐元数据"""
df = pd.read_csv(raw_csv_path, encoding='utf-8-sig')
print(f"原始数据量: {len(df)}")
# 1. 去重(基于歌名和艺术家)
df.drop_duplicates(subset=['title', 'artist'], keep='first', inplace=True)
print(f"去重后数据量: {len(df)}")
# 2. 处理缺失值
# 如果艺术家缺失,用‘Unknown Artist’填充
df['artist'].fillna('Unknown Artist', inplace=True)
# 专辑缺失可以保留空字符串
df['album'].fillna('', inplace=True)
# 3. 规范化歌名(移除括号内的现场版、Remix等信息,可选)
# 例如:”后来 (Live)“ -> ”后来“
df['title_clean'] = df['title'].apply(lambda x: re.sub(r'\s*\(.*?\)\s*', '', x).strip())
# 如果清洗后为空,则用原歌名
df['title_clean'] = df.apply(
lambda row: row['title'] if row['title_clean'] == '' else row['title_clean'],
axis=1
)
# 4. 分离歌手和feat.信息(如果存在)
# 例如:”Artist A feat. Artist B“ -> main_artist: ”Artist A“, featured_artists: ”Artist B“
def split_artist(artist_str):
if 'feat.' in artist_str.lower() or 'ft.' in artist_str.lower():
# 简单分割,实际可能更复杂
parts = re.split(r'\s+feat\.\s+|\s+ft\.\s+', artist_str, flags=re.IGNORECASE)
main = parts[0].strip()
feat = parts[1].strip() if len(parts) > 1 else ''
return main, feat
return artist_str.strip(), ''
artist_split_result = df['artist'].apply(split_artist)
df['main_artist'] = artist_split_result.apply(lambda x: x[0])
df['featured_artists'] = artist_split_result.apply(lambda x: x[1])
# 5. 生成一个唯一ID(例如,歌名和艺术家的MD5哈希)
import hashlib
def generate_song_id(title, artist):
s = f"{title}_{artist}".encode('utf-8')
return hashlib.md5(s).hexdigest()[:8] # 取前8位
df['song_id'] = df.apply(lambda row: generate_song_id(row['title_clean'], row['main_artist']), axis=1)
# 6. 保存清洗后的数据
# 选择要保留的列
columns_to_keep = ['song_id', 'title', 'title_clean', 'artist', 'main_artist',
'featured_artists', 'album', 'duration_str', 'duration_sec',
'source_url', 'tags']
df_clean = df[columns_to_keep]
# 确保输出目录存在
Path(output_csv_path).parent.mkdir(parents=True, exist_ok=True)
df_clean.to_csv(output_csv_path, index=False, encoding='utf-8-sig')
print(f"清洗后的数据已保存至: {output_csv_path}")
print(df_clean.head())
return df_clean
 
# 运行清洗
if __name__ == '__main__':
# 假设我们有一个手动创建的模拟数据CSV,用于演示
# 在实际项目中,这里应该是爬虫保存的 raw data
import io
# 模拟数据
mock_data = """title,artist,album,duration_str,source_url
后来,刘若英,我等你,5:41,https://example.com/song1
十年,陈奕迅,黑白灰,3:57,https://example.com/song2
她说,林俊杰,她说,5:20,https://example.com/song3
泡沫,邓紫棋,Xposed,4:33,https://example.com/song4
"""
raw_df = pd.read_csv(io.StringIO(mock_data))
raw_df['tags'] = ['sentimental'] * len(raw_df)
raw_df.to_csv('./data/raw/mock_music_list.csv', index=False)
clean_and_enhance_data('./data/raw/mock_music_list.csv', './data/processed/cleaned_music_list.csv')

运行后,你将得到一个干净、结构化的音乐元数据表格,这是后续所有操作的基础。

5. 第二步:音频文件获取与处理(合法途径探讨)

这是技术、法律和伦理交织最复杂的部分。我们必须强调,任何音频文件的获取都必须建立在合法授权的基础上。 以下提供几种完全合法的技术思路:

5.1 思路一:使用免费、无版权音乐库

许多网站提供CC协议(知识共享)或公有领域的音乐。我们可以爬取其元数据,并通过其提供的官方下载链接获取。

PYTHON
# file: downloader/audio_downloader.py (示例框架)
import yt_dlp
import pandas as pd
from pathlib import Path
import logging
 
logging.basicConfig(level=logging.INFO)
 
class LegalAudioDownloader:
"""合法音频下载器示例(需配合具体网站API或规则)"""
def __init__(self, output_dir: Path):
self.output_dir = output_dir
self.output_dir.mkdir(parents=True, exist_ok=True)
# 配置yt-dlp(用于支持那些允许下载的网站)
self.ydl_opts = {
'format': 'bestaudio/best',
'outtmpl': str(self.output_dir / '%(title)s.%(ext)s'),
'quiet': True,
'no_warnings': True,
'postprocessors': [{
'key': 'FFmpegExtractAudio',
'preferredcodec': 'mp3', # 转换为mp3
'preferredquality': '192', # 比特率
}],
# 非常重要:限制下载速度,避免对服务器造成压力
'ratelimit': 500000, # 500 KB/s
}
def download_from_url(self, url: str, song_name: str):
"""从单个URL下载音频"""
try:
with yt_dlp.YoutubeDL(self.ydl_opts) as ydl:
# 添加额外信息到文件名
self.ydl_opts['outtmpl'] = str(self.output_dir / f'{song_name}.%(ext)s')
ydl.download([url])
logging.info(f"下载成功: {song_name}")
return True
except Exception as e:
logging.error(f"下载失败 {song_name}: {e}")
return False
def batch_download_from_dataframe(self, df: pd.DataFrame, url_column: str, name_column: str):
"""从DataFrame批量下载"""
success_count = 0
for idx, row in df.iterrows():
url = row[url_column]
name = row[name_column]
if pd.isna(url) or url == '':
logging.warning(f"跳过 {name},URL为空")
continue
# 检查是否已存在
existing_files = list(self.output_dir.glob(f"{name}.*"))
if existing_files:
logging.info(f"文件已存在,跳过: {name}")
success_count += 1
continue
if self.download_from_url(url, name):
success_count += 1
# 建议添加延时,尊重服务器
import time
time.sleep(2)
logging.info(f"批量下载完成。成功: {success_count}/{len(df)}")
return success_count
 
# 注意:此代码仅为框架。实际使用时,`url`必须指向明确允许下载的音频源。

5.2 思路二:使用公开的音频数据集

对于机器学习项目,直接使用现有的学术或开源数据集更规范。例如:

  • GTZAN Genre Collection:音乐流派分类。
  • FMA (Free Music Archive):一个大规模、高质量的合法音频数据集。
  • MUSDB18:音乐源分离数据集。

你可以编写脚本,从这些数据集中筛选出符合“伤感”特征(通常通过标签或元数据)的片段。

5.3 思路三:本地文件处理与特征提取(如果你已有合法音频)

如果你已经拥有一个本地的合法音乐库,可以跳过下载,直接进行下面的处理和分析。

PYTHON
# file: utils/audio_processor.py
from pydub import AudioSegment
import librosa
import librosa.display
import numpy as np
import matplotlib.pyplot as plt
from pathlib import Path
 
class AudioAnalyzer:
"""音频分析器,用于提取特征"""
@staticmethod
def load_audio(file_path: Path, sr=22050):
"""使用librosa加载音频,返回音频时间序列和采样率"""
try:
y, sr = librosa.load(str(file_path), sr=sr)
return y, sr
except Exception as e:
print(f"加载音频失败 {file_path}: {e}")
return None, sr
@staticmethod
def extract_basic_features(y, sr):
"""提取基础音频特征"""
features = {}
# 节奏 (BPM)
tempo, _ = librosa.beat.beat_track(y=y, sr=sr)
features['tempo'] = tempo[0] if len(tempo) > 0 else 0
# 频谱质心 (Spectral Centroid) - 与“明亮度”相关,伤感音乐可能偏低
spectral_centroid = librosa.feature.spectral_centroid(y=y, sr=sr)
features['spectral_centroid_mean'] = np.mean(spectral_centroid)
features['spectral_centroid_std'] = np.std(spectral_centroid)
# 过零率 (Zero Crossing Rate) - 与打击感相关
zero_crossing_rate = librosa.feature.zero_crossing_rate(y)
features['zcr_mean'] = np.mean(zero_crossing_rate)
# 梅尔频率倒谱系数 (MFCCs) - 常用于音色、乐器识别
mfccs = librosa.feature.mfcc(y=y, sr=sr, n_mfcc=13)
for i in range(mfccs.shape[0]):
features[f'mfcc_{i+1}_mean'] = np.mean(mfccs[i])
features[f'mfcc_{i+1}_std'] = np.std(mfccs[i])
return features
@staticmethod
def plot_waveform_and_spectrum(y, sr, title="Audio"):
"""绘制波形图和频谱图"""
plt.figure(figsize=(12, 8))
plt.subplot(2, 1, 1)
librosa.display.waveshow(y, sr=sr, alpha=0.5)
plt.title(f'{title} - Waveform')
plt.xlabel('Time (s)')
plt.ylabel('Amplitude')
plt.subplot(2, 1, 2)
D = librosa.amplitude_to_db(np.abs(librosa.stft(y)), ref=np.max)
librosa.display.specshow(D, sr=sr, x_axis='time', y_axis='log')
plt.colorbar(format='%+2.0f dB')
plt.title(f'{title} - Spectrogram')
plt.tight_layout()
plt.show()
 
# 示例:分析一首本地音频文件
if __name__ == '__main__':
# 假设有一首合法且已下载的示例音频
# audio_file = Path('./data/audio/example_song.mp3')
# if audio_file.exists():
# analyzer = AudioAnalyzer()
# y, sr = analyzer.load_audio(audio_file)
# if y is not None:
# features = analyzer.extract_basic_features(y, sr)
# print("提取的特征:", features)
# # analyzer.plot_waveform_and_spectrum(y, sr, title=audio_file.stem)
# else:
# print("示例音频文件不存在,跳过特征提取演示。")
print("AudioAnalyzer 类定义完成。")

6. 第三步:构建“伤感”标签体系与简单分类器

“伤感”是主观标签。我们可以结合元数据(如歌名、歌词关键词)和音频特征,构建一个简单的规则或机器学习分类器。

6.1 基于元数据的规则过滤

PYTHON
# file: main.py (续)
def filter_by_metadata_rules(df: pd.DataFrame):
"""基于歌名、艺术家等元数据的简单规则过滤"""
# 定义可能包含伤感关键词的歌名词汇(示例)
sentimental_keywords_in_title = [
'哭', '泪', '伤', '痛', '离别', '分手', '忘记', '回忆', '寂寞', '孤独',
'心碎', '后悔', '错过', '后来', '十年', '她说', '泡沫' # 示例歌曲
]
# 定义可能演唱伤感歌曲的艺术家(示例)
sentimental_artists = ['刘若英', '陈奕迅', '林俊杰', '邓紫棋', '张惠妹', '孙燕姿']
def is_sentimental_by_rule(row):
# 检查歌名
title = row['title_clean']
if any(keyword in title for keyword in sentimental_keywords_in_title):
return True
# 检查主要艺术家
if row['main_artist'] in sentimental_artists:
return True
# 可以扩展检查歌词(如果有歌词数据)
return False
df['rule_based_sentimental'] = df.apply(is_sentimental_by_rule, axis=1)
sentimental_df = df[df['rule_based_sentimental'] == True].copy()
print(f"基于元数据规则,筛选出 {len(sentimental_df)} 首潜在伤感歌曲")
return sentimental_df

6.2 基于音频特征的简单分类(需特征数据)

如果我们已经提取了音频特征,可以尝试简单的阈值分类。

PYTHON
def classify_by_audio_features(features_df: pd.DataFrame):
"""基于音频特征的简单阈值分类(非常初级)"""
# 假设features_df包含之前提取的tempo, spectral_centroid_mean等列
# 伤感音乐通常可能:节奏较慢,频谱质心较低(声音更低沉)
conditions = (
(features_df['tempo'] < 90) & # BPM较慢
(features_df['spectral_centroid_mean'] < 2000) # 频谱质心较低
)
features_df['feature_based_sentimental'] = conditions
return features_df

在实际项目中,你可以收集一批明确标记“伤感/非伤感”的歌曲,提取特征,训练一个简单的分类模型(如逻辑回归、SVM或随机森林)。

7. 第四步:构建一个简单的音乐查询API

有了清洗后的元数据(和本地音频路径),我们可以用Flask或FastAPI快速搭建一个查询服务。

PYTHON
# file: app.py
from flask import Flask, request, jsonify
import pandas as pd
from pathlib import Path
import json
 
app = Flask(__name__)
 
# 加载数据
DATA_PATH = Path('./data/processed/cleaned_music_list.csv')
if DATA_PATH.exists():
df = pd.read_csv(DATA_PATH)
else:
# 如果没有数据,创建一个空的DataFrame
df = pd.DataFrame(columns=['song_id', 'title', 'artist', 'duration_sec', 'tags'])
print("警告:未找到数据文件,使用空数据集。")
 
@app.route('/api/songs', methods=['GET'])
def get_songs():
"""获取歌曲列表,支持简单过滤"""
artist = request.args.get('artist', '').strip()
title_keyword = request.args.get('title', '').strip()
min_duration = request.args.get('min_duration', type=int)
max_duration = request.args.get('max_duration', type=int)
result_df = df.copy()
# 应用过滤器
if artist:
result_df = result_df[result_df['artist'].str.contains(artist, case=False, na=False)]
if title_keyword:
result_df = result_df[result_df['title'].str.contains(title_keyword, case=False, na=False)]
if min_duration is not None:
result_df = result_df[result_df['duration_sec'] >= min_duration]
if max_duration is not None:
result_df = result_df[result_df['duration_sec'] <= max_duration]
# 转换为字典列表返回
songs = result_df.to_dict('records')
return jsonify({
'count': len(songs),
'songs': songs
})
 
@app.route('/api/songs/<song_id>', methods=['GET'])
def get_song_by_id(song_id):
"""根据ID获取单首歌曲详情"""
song = df[df['song_id'] == song_id]
if song.empty:
return jsonify({'error': 'Song not found'}), 404
return jsonify(song.iloc[0].to_dict())
 
@app.route('/api/sentimental', methods=['GET'])
def get_sentimental_songs():
"""获取标记为伤感的歌曲(示例)"""
# 这里假设我们有一个‘sentimental’标签
sentimental_songs = df[df['tags'].apply(lambda x: 'sentimental' in str(x).lower())]
return jsonify({
'count': len(sentimental_songs),
'songs': sentimental_songs.to_dict('records')
})
 
if __name__ == '__main__':
app.run(debug=True, port=5000)

运行这个Flask应用后,你就可以通过浏览器或curl访问API了:

BASH
# 启动API
python app.py
 
# 在另一个终端测试
curl "http://127.0.0.1:5000/api/songs?artist=陈奕迅"
curl "http://127.0.0.1:5000/api/sentimental"

8. 项目总结与核心收获

通过这个“伤感音乐合集”项目,我们实际上完成了一个小型的数据工程与后端服务的闭环。回顾一下关键步骤和技术点:

  1. 数据采集:使用requests+BeautifulSoup从网页提取结构化数据,学习了HTTP请求、HTML解析和简单的反爬应对(如User-Agent)。
  2. 数据清洗:使用pandas进行去重、缺失值处理、字符串规范化,生成了干净、可用的数据集。
  3. 数据获取(合法途径):探讨了从免费音源下载、使用公开数据集等合法方案,并强调了版权的重要性。
  4. 音频处理:使用librosapydub进行音频加载、特征提取和可视化,接触了音乐信息检索(MIR)的基础。
  5. 标签化与分类:结合规则和简单模型,为音乐打上“伤感”标签,这是一个典型的数据标注与分类问题。
  6. 服务化:使用Flask构建REST API,让数据可以通过HTTP接口被查询和使用。

这个项目的真正价值不在于收集了几首伤感的歌,而在于提供了一个完整的、可复现的技术流水线模板。你可以轻松地将这个模板应用到其他领域:

  • 构建“学习专注”白噪音合集:采集雨声、咖啡馆背景音等。
  • 构建“经典电影配乐”库:从电影原声带网站抓取信息。
  • 构建“播客节目”索引:聚合和分析不同平台的播客元数据。

下一步可以深入的方向:

  • 爬虫进阶:使用Scrapy框架、处理动态页面(Selenium/Playwright)、应对更复杂的反爬机制。
  • 数据存储:将数据存入SQLitePostgreSQL数据库,并设计更合理的表结构。
  • 特征工程与机器学习:提取更多音频特征(如色度特征、节拍特征),收集更多标注数据,训练一个真正能区分音乐情感的模型。
  • 前端展示:用Vue.jsReact配合API,做一个美观的歌单展示页面。
  • 部署上线:使用Docker容器化应用,部署到云服务器。

技术项目的乐趣,往往就在于将一个个模糊的需求,拆解成清晰、可执行的步骤,并用代码将其实现。希望这个从“伤感音乐合集”出发的项目,能为你打开一扇通往数据世界的新大门。

网易云音乐API实战:5分钟搭建个人音乐推荐系统(附完整代码)
本文基于网易云音乐公开API,利用Python快速构建轻量级个人音乐推荐系统。涵盖环境配置、热门/个人歌单数据采集、基于内容过滤的推荐算法实现、多模块系统集成及常见问题排查。核心依赖包括歌单特征提取、相似度匹配与推荐排序,适用于无机器学习背景的开发者快速上手。
白追追
192
QQ音乐解析工具终极指南快速解锁完整音乐生态链
本文介绍了一款基于Python的QQ音乐解析工具,支持智能搜索、高质量音乐数据采集及完整元数据获取,适用于个人音乐库建设、内容创作与音乐数据分析,具备良好的开发者友好性和扩展性。
滑姗珊
903
Python+Spotify API打造个性化音乐分析工具
本文介绍如何使用Python和Spotify官方API构建个性化音乐分析工具,涵盖环境配置、OAuth认证封装、关键数据端点调用(如音频特征、收听时段、艺人信息)、数据清洗与可视化(雷达图、时间模式分析),以及应对速率限制、SQLite持久化、音乐口味变迁分析和艺人关系网络构建等关键技术。
XY同学
221
CCMusic音乐流派分类实战:Python爬虫数据预处理与模型训练
本文介绍基于CCMusic模型的音乐流派分类全流程实践,涵盖Python爬虫采集带标签音频数据、音频预处理(如标准化、频谱图生成)、数据集构建、模型微调训练及评估,并通过Flask封装为可部署的音乐分类API。重点聚焦于音频特征工程与迁移学习在真实场景下的落地应用。
MCPlayer542
306
大数据毕业设计:音乐数据采集分析可视化系统 爬虫+深度学习+推荐算法+可视化(源码)✅
本文介绍了2023-2024年的计算机专业毕业设计项目,使用Flask、Vue、scrapy和协同过滤算法构建音乐数据分析与推荐系统。项目涵盖了数据采集、分析、可视化和个性化推荐,如音乐热度分析、情感分析和推荐算法应用。
源码之家
2113
探索音乐新境界Spotipy - 轻量级Python库,连接Spotify Web API
本文介绍轻量级Python库Spotipy,用于对接Spotify Web API。涵盖环境准备、pip安装、Spotify开发者凭证申请(Client ID/Secret)、认证流程及基础编程实践,重点演示如何通过API获取艺人专辑等结构化音乐元数据,并提供常见错误排查方案。
翟苹星Trustworthy
700
抖音TikTok数据采集神器零基础掌握完整下载解决方案
DouK-Downloader是一款开源的抖音与TikTok数据采集工具,支持视频、音乐、直播、评论、合集等多类型内容的高质量下载与结构化提取。提供终端交互、Web API、Docker容器化部署等多种使用模式,具备Cookie身份验证、批量处理、多格式输出(MP4/MP3/CSV/SQLite)及自动化采集能力,适用于内容备份、运营分析与开发者集成。
郑微殉
962
QQ音乐数据解析全攻略高效获取完整音乐生态资源
本文介绍了一个基于Python的QQ音乐数据解析工具,支持高效获取歌曲、专辑、歌词等元数据及高品质音频流。适用于个人音乐库建设、内容创作与音乐数据分析,具备模块化架构与性能优化机制,助力开发者快速集成音乐生态资源。
梅品万Rebecca
1099
QQ音乐解析终极指南快速解锁完整音乐生态链
本文介绍了一款基于Python的QQ音乐解析工具,涵盖智能搜索、高品质音频流获取及完整元数据采集等功能。适用于个人音乐库建设、内容创作与数据分析场景,提供详细的技术架构与使用配置建议,助力开发者高效集成音乐生态能力。
傅尉艺Maggie
520
QQ音乐解析终极指南如何免费获取全网音乐资源
本指南详解基于Python的QQ音乐开源解析工具,涵盖Cookie凭证获取、智能搜索、完整元数据提取、批量歌单导出、MV解析下载及榜单同步等核心功能。重点介绍其对QQ音乐Web API的逆向分析与调用方法,支持绿钻歌曲解析与歌词提取,适用于音乐数据采集、本地化存储与跨平台管理等技术场景。
霍曙柏
121
Python数据管道实战:音乐节数据解析到Streamlit可视化应用
本文以音乐节演出数据为案例,构建端到端Python数据管道基于SQLAlchemy设计星型模型数据库,使用Pandas清洗解析非结构化文本(如'JOVYNN @ HIVE Festival 2026 | SLEEPLESS'),并用Streamlit开发交互式Web应用实现数据查询与可视化。涵盖环境配置、ORM建模、ETL流程、错误处理及工程化最佳实践。
weixin_33802505
634
5分钟打造智能副屏Turing Smart Screen Python终极指南
本文详解如何使用开源Python项目Turing Smart Screen实现USB-C小屏幕的智能系统监控。涵盖硬件连接、跨平台软件配置、主题定制及传感器数据采集(psutil/GPUtil/LibreHardwareMonitor),支持多品牌屏幕、自定义插件开发与主题编辑,适用于系统监控、游戏FPS显示、开发者调试及创意工作流等场景。
樊元隽
462
DouK-Downloader抖音TikTok数据采集下载终极指南
DouK-Downloader是一款基于Python 3.12+的开源数据采集工具,支持抖音与TikTok双平台,提供视频、音乐、直播、评论、合集等多类型内容下载与结构化采集。具备终端交互、Web API、后台监听及Web UI四种运行模式,支持Cookie鉴权、代理配置、断点续传及多种存储格式(MP4/MP3/JSON/CSV/XLSX)。面向内容创作者、运营人员及开发者,适用于素材收集、竞品分析与个人备份等场景。
鲁景晨
431
精选100个Python实战项目案例,送给缺乏实战经验的你
本文为Python初学者提供了100个实战项目列表,涵盖从图片处理、游戏开发到数据分析、网络编程等多方面,旨在帮助学习者巩固知识,提升技能,保持学习热情。
怪可爱的码农
27411
DouK-Downloader终极指南5分钟学会抖音TikTok数据采集
DouK-Downloader是一款开源免费的抖音与TikTok数据采集工具,支持视频、评论、用户信息、热榜、直播等多维度数据抓取。提供终端交互、Web API和Web UI三种使用模式,适用于新手下载、开发者集成、自动监控及批量处理场景。需配置有效Cookie,基于Python开发,兼容命令行与图形界面,强调安全合规与文件管理最佳实践。
包力文Hardy
444
终极音乐歌词获取神器网易云QQ音乐歌词一键搞定免费工具
163MusicLyrics是一款开源免费的音乐歌词获取处理工具,支持网易云音乐和QQ音乐双平台,提供精确/模糊搜索、一键保存(多种格式及编码)、批量歌词下载等功能。具备简洁GUI界面,涵盖搜索源选择、歌词预览、时长显示及结构化结果列表,适用于音乐数据采集与本地歌词管理场景。
瞿兴亮Sybil
896
【推荐系统工程师私藏笔记】Python实现Spotify级音乐推荐的7个秘密
本文深入讲解基于Python音乐推荐系统构建全过程,涵盖数据预处理、用户行为建模、协同过滤、深度表示学习及上下文感知混合推荐策略。重点介绍Sparse矩阵构建、时间衰减因子应用、LightFM与Implicit库实践,并探讨模型上线部署、监控反馈与弹性伸缩等工程化挑战,助力打造近实时高性能推荐系统。
QuickDebug
1132
基于 DouYin 打造抖音热榜数据管道定时采集 + MongoDB 存储实战
本文基于开源库DouYin构建抖音热榜数据采集与存储管道,涵盖定时采集、JSON解析、MongoDB结构化存储三大核心环节。通过MongoHandler实现自动分类写入与幂等upsert去重,结合cron实现全自动运行。重点介绍DouYin的热榜/视频/音乐接口调用、MongoDB连接配置及生产级避坑方案,适用于舆情监控、热点分析等数据基建场景。
邬楠满Seaman
648
JSP音乐推荐系统54n6q--程序+源码+数据库+调试部署+开发环境
该博客围绕JSP音乐推荐系统展开,介绍了选题背景、研究目标与内容,包括数据采集、用户画像构建、推荐算法研究等。还阐述了研究方法与技术路线,使用Python、MySQL等技术。此外,说明了开发流程,如环境搭建、创建Web项目、编写JSP页面等。
Kittyxia001
709
音乐API接口用于音乐API调用
音乐API接口是应用程序编程接口(API)的一种,专门设计用于音乐相关的服务,如播放、搜索、推荐和获取音乐元数据。这些接口允许开发者构建音乐应用,整合音乐平台的功能,为用户提供丰富的音乐体验。1.
爱祟祟
2733
python实现音乐播放器
通过以上步骤,我们可以构建一个功能完备的Python-Django音乐播放器应用,与网易音乐API无缝对接,为用户提供流畅的音乐体验。在实践中,不断迭代和优化,可以打造一个高度定制化的个人音乐平台。
小牛牛先生
2896
python-qq-music-api:QQ音乐APIpython实现)
本文介绍了一个Python类,该类通过调用QQ音乐API接口实现音乐数据的获取,包括搜索关键词、获取歌手信息、粉丝数、歌曲收藏数等。同时,代码示例展示了如何使用xlwt库将歌手信息统计结果输出到Exc
空气安全讲堂
1584
网易云音乐可用的api
总之,网易云音乐API为开发者提供了丰富的音乐资源和功能,使得我们可以构建出富有创新性的音乐应用。然而,使用时务必遵守平台规定,尊重用户隐私,确保数据安全。
Demo.demo
12215
虾米音乐API
**音乐推荐系统**开发者可以通过API获取虾米音乐的歌曲数据,结合用户的听歌历史和偏好,打造个性化的音乐推荐。2.
880
网易云音乐可用的API
**歌曲信息获取**:API可能会提供接口用于检索歌曲的基本信息,如歌曲ID、歌手、专辑、时长、歌词等。这对于构建音乐推荐系统或播放器应用非常关键。3.
NeverSettle101
4666
网易云音乐api
总的来说,网易云音乐API为开发者提供了丰富的音乐服务接口,通过合理利用这些接口,开发者可以构建出具有个性化音乐体验的应用,例如音乐推荐系统、自定义播放器等。
qq_36965460
4861
netease-cloud-music-api:网易云音乐直链解析 API
【标题】"netease-cloud-music-api:网易云音乐直链解析 API" 是一个Python项目,专注于获取网易云音乐的直链,使用户能够绕过官方限制,直接访问音乐资源。
莊謙
1033
Python 项目开发实战 - Python flask 项目 - 甜橙音乐网源码 - 毕业设计
Python Flask项目实战:甜橙音乐网开发详解》在当今的互联网时代,Python作为一款高效、简洁且功能强大的编程语言,受到了众多开发者尤其是Web开发者的喜爱。
风老魔
668
Python实现音乐推荐系统.rar
这些数据可以从音乐流媒体平台的API获取,或者从公开的数据集如Last.fm、Million Song Dataset等获取。**一、数据预处理**1. 数据清洗去除重复项、异常值和缺失值。2.
Wency(王斯-CUEB)
1149