尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

中文歌词数据集ChineseLyrics清洗与NLP任务实战指南

发布时间:2026/9/29 15:39:58

资讯中心
01
ARTICLE

中文歌词数据集ChineseLyrics清洗与NLP任务实战指南

中文歌词数据集ChineseLyrics清洗与NLP任务实战指南
简介中文歌词数据库ChineseLyrics是一份面向自然语言处理与数据分析从业者的华语歌词语料集覆盖2019年以前绝大多数华语歌手的十余万首歌曲共收录四千余位歌手其中作品数二十首以上的超过千人、一百首以上的两百余人。数据已按歌手聚类并按作品数量降序排列每条记录包含歌名、歌手和完整歌词字段便于直接进行词频统计、文本分类、情感分析及押韵规律研究。资源包共六个文件以五个JSON数据文件为主体另附一份Markdown说明文档压缩包整体大小为34.15MB结构清晰、加载轻量。除原始歌词外还额外提供基于全量语料统计的词频排序表、句子开头词语频次表和拼音押韵表可帮助研究者快速开展中文歌词的语言特征分析也可用于搭建歌词生成、风格分类等模型。该资源目前已有1068人学习使用适合具备一定Python和数据处理基础的NLP爱好者、算法工程师及语言学研究者作为语料补充。1. ChineseLyrics 中文歌词数据库先解决领域数据荒再谈模型很多做中文 NLP 的工程师默认从新闻、微博、评论这类语料起步等模型上线后才发现换到歌词这种高口语、强押韵、多重复的文本上情感分析分数掉得离谱主题模型也把“失恋”和“励志”混成一锅粥。ChineseLyrics 中文歌词数据库就是为这类自然语义处理任务准备的数据集它把散落各处的华语歌词整理成带歌手、歌名、专辑等字段的结构化语料解决了“中文歌词没有干净公开数据”的启动问题。对于入门中文 NLP 的工程师或者做歌曲推荐、弹幕情感分析、歌词生成方向的团队这个数据集是能直接跑通全流程的起点。下面按我实际落地的方式把字段清洗、切分粒度、三个典型任务和踩过的坑写清楚。2. 从 ChineseLyrics 拿到标准 NLP 数据集字段、编码和切分粒度ChineseLyrics 这类数据集的原始形态通常是 JSON 行或 CSV 表格歌词文本、歌手、歌名、专辑字段都有但因为来源是网页抓取质量参差。直接拿去跑模型你会先遇到中文编码、繁简混排、重复副歌、空白行等基础问题。大多数 NLP 教程不会讲这些因为通用语料已经被清洗得很干净而歌词数据恰恰需要你自己补上这一层。2.1 歌词和新闻语料的三个结构差异决定预处理优先级歌词文本和新闻语料最大的不同是“重复”。新闻不会把同一段话原样写两遍但歌词几乎每首都带副歌而且副歌会整体重复 2 到 4 遍。这意味着你不能对全文本做一次性的drop_duplicates()去重否则副歌被删光歌曲结构就破坏了但你也必须在生成任务里处理重复否则模型会变成复读机。这个矛盾是歌词数据集特有的。第二个差异是标点稀疏。歌词经常一行就是一句话甚至一行只有“啦啦啦”“Yeah yeah”这种拟声词逗号句号都省了。分词器遇到这种连续汉字串会把“雨下整夜我的爱溢出就像雨水”切成一长段情感词和主题词混在一起。所以在切分前要先按物理行切分再决定哪些行有语义。第三个差异是停用词表不一样。新闻停用词里的“报道、记者、表示”在歌词里没有意义歌词里的“啦、哦、呀、OH、YEAH、哗啦啦”反而会污染主题模型。用默认停用词表跑 LDA主题里全是你我他。2.2 字段怎么选歌手、歌名、专辑、语言标记的价值和陷阱ChineseLyrics 的常见字段包括歌曲名、歌手、专辑、歌词全文部分版本带语言标记、作词作曲。导入时我一般保留前三个语言标记要看情况因为这些字段对 NLP 任务的价值不同。歌手字段是最好的弱标签。同一歌手的歌词在情感倾向上有明显规律比如苦情歌歌手和陈奕迅的用词风格差别很大。做歌手分类或歌单推荐时这个字段可以直接当label。但有个陷阱合唱歌曲的歌手字段是两个人翻唱歌曲的歌手字段是翻唱者Live 版还带着“Live”字样。如果直接按歌手分组模型会学到“张惠妹 vs 张惠妹 Live”这种伪差异。歌名字段适合做检索和展示不适合做分类标签。同名歌曲很多国语的《红豆》和王菲的《红豆》不是同一首歌名相同但歌词差异巨大。因此一般只把歌名当作主键的一部分不参与特征。语言标记则要小心。中文歌词数据集里除了普通话还有大量粤语、闽南语、少量英语单词。粤语歌词保留“嘅、哋、唔”这些字转成简体时会被 OpenCC 误转或漏转如果任务目标是普通话情感分析最好先把粤语行过滤掉或者单独建一个粤语子集不要混在一起训练。2.3 切分粒度怎么选整首、按句、按语义块歌词的 NLP 任务不同切分粒度完全不同这是新手最容易翻车的地方。下面这张表是我实践下来的推荐配置。任务类型推荐切分粒度原因文本情感分类按句切过滤少于 4 个汉字整首歌情感有起承转合按句能拿到更多训练样本主题建模 LDA整首保留不切句主题词需要上下文共现切太碎会变成多个短文本碎片歌词生成按行切保留换行符生成器需要学习“句长节奏”整首输入会优先学会复制歌手风格分类整首切块每块 200 字语法特征在句中不明显在段落里更稳按句切分时我建议保留至少 4 个汉字。歌词里经常出现“啊”“哦”“嘿”这种单字行切进数据集只会让模型学到无意义的情感噪声。如果切出来是“我爱你不后悔”长度正好 5 个字可以用如果是“啦”就直接丢掉。按语义块切分要更精细一点。副歌如果重复两遍你可以只保留第一遍第二遍删除这样既保住歌曲结构又避免生成任务里同句重复出现。常见做法是按连续 4 行取哈希如果后续段落和前面某段哈希一致就标记为副歌重复只保留第一次出现。3. 把 ChineseLyrics 原始库洗干净从 JSON 到可训练 CSV 的完整脚本这一节的脚本以“每行一条 JSON”的 ChineseLyrics 导出文件为输入。常见格式是{song:七里香,singer:周杰伦,album:七里香,lyrics:窗外的麻雀 在电线杆上多嘴}如果你下载到的是 CSV把pd.read_csv替换掉pd.read_json即可。下面的处理流程同时兼容两种来源。3.1 用 OpenCC 统一繁简并识别非中文行中文歌词库的原始内容里繁体、简体、粤语用字、英文注释混杂。我先把所有文本统一成简体再过滤掉纯英文或拼音行避免后续分词器把“OH MY GOD”当成一堆字母碎片。import json import re import pandas as pd from opencc import OpenCC cc OpenCC(t2s) # 繁体转简体 def clean_text(text): text cc.convert(text or ) # 保留中文、英文、数字和常用标点全角标点统一成半角 text text.replace(, ,).replace(。, .).replace(, !).replace(, ?) # 行级过滤只保留至少含 2 个中文汉字的行 lines [] for line in text.split(\n): zh_chars re.findall(r[\u4e00-\u9fff], line) if len(zh_chars) 2: lines.append(line.strip()) return \n.join(lines) def load_lyrics_json(path): records [] with open(path, r, encodingutf-8) as f: for line in f: if line.strip(): obj json.loads(line) obj[lyrics] clean_text(obj.get(lyrics, )) records.append(obj) return pd.DataFrame(records) df load_lyrics_json(chinese_lyrics.jsonl) print(df.shape)说明OpenCC(t2s)处理常见繁简转换但粤语特有字“嘅、咁、唔”不会被转换这些字会被保留因为它们本身就有语义。中文汉字正则用[\u4e00-\u9fff]这个范围覆盖常用简体字和繁体汉字但不会匹配日文假名适合歌词场景。过滤条件设为“至少 2 个中文汉字”是为了排除“Yeah yeah”和“深呼吸 123”这种半英文行。3.2 去重不能只靠 DataFrame.drop_duplicates同一个歌手的同一首歌在不同抓取来源里会出现多次歌词版本可能相差几个字。直接drop_duplicates(subset[song,singer])会随机保留一条可能留下歌词残缺的版本。我的做法是先算歌词长度再按“歌手歌名歌词哈希”排序保留每首歌词数最多的那条。import hashlib def lyric_hash(text): # 去掉所有空白后取 sha1 前 16 位减少长文本内存开销 normalized re.sub(r\s, , text) return hashlib.sha1(normalized.encode(utf-8)).hexdigest()[:16] df[hash] df[lyrics].apply(lyric_hash) df[char_count] df[lyrics].apply(lambda x: len(re.sub(r\s, , x))) # 对同一首歌的同一个版本按歌词长度排序保留最长 df df.sort_values(char_count, ascendingFalse) df df.drop_duplicates(subset[song, singer, hash], keepfirst) df df.sort_values(song).reset_index(dropTrue)说明哈希先去掉空白是因为不同来源的换行符和空格不一致但歌词内容相同对同一首歌只要字符顺序一致哈希就一致。排序后drop_duplicates(keepfirst)保证保留最长版本。如果你不想完全删除重复副歌至少在这里可以识别重复行后续生成任务用hash列做段落去重。char_count参数会在后续作为过滤条件使用。歌词少于 50 个字的歌曲往往是纯音乐或伴奏或者抓取失败我一般直接丢弃。3.3 按歌手分组做训练测试划分防止数据泄漏歌词生成和歌手分类任务里数据泄漏是一个很隐蔽的坑。如果随机train_test_split同一个歌手的歌曲会同时出现在训练集和测试集模型只要记住歌手特征就能在测试集上拿高分换一个新歌手就崩。解决办法是分组划分。from sklearn.model_selection import GroupShuffleSplit X df[lyrics] y df[singer] groups df[singer] # 以歌手为组 gss GroupShuffleSplit(n_splits1, test_size0.2, random_state42) train_idx, test_idx next(gss.split(X, y, groups)) df_train df.iloc[train_idx].reset_index(dropTrue) df_test df.iloc[test_idx].reset_index(dropTrue) print(df_train[singer].nunique(), df_test[singer].nunique()) print(重叠歌手数:, len(set(df_train[singer]) set(df_test[singer])))说明GroupShuffleSplit的groups参数必须传入歌手列test_size0.2表示拿出 20% 的歌手及其全部歌曲做测试集。这里random_state42固定随机种子保证下次复现时划分结果一致。最后那行打印重叠歌手数如果大于 0说明分组参数没传对测试集混入了训练歌手的数据。如果你做的是情感分析而不是歌手识别按句切分后仍然建议按歌手分组拆分。因为同一个歌手的情感表达习惯接近随机拆分会让模型学到歌手风格而不是学到情感语义。3.4 输出为 Parquet保留中文不折腾清洗完的数据集建议输出为 Parquet 而不是 CSV。Parquet 会自动处理 UTF-8 编码和数据类型Excel 打开 CSV 时中文乱码的问题在 Parquet 上不存在。歌词里的换行符也能原样保存。df_train.to_parquet(lyrics_train.parquet, indexFalse) df_test.to_parquet(lyrics_test.parquet, indexFalse) # 同时保留一份按行切分的句子级文件方便情感分析直接读 row_records [] for _, r in df.iterrows(): for line in r[lyrics].split(\n): clean_line line.strip() if len(re.findall(r[\u4e00-\u9fff], clean_line)) 4: row_records.append({ singer: r[singer], song: r[song], line: clean_line, char_count: len(clean_line) }) df_lines pd.DataFrame(row_records) df_lines.to_parquet(lyrics_lines.parquet, indexFalse)说明行级文件里char_count是整行字符数不是中文字符数。它作为后续情感分析的一个次要特征用来过滤过短行。这句代码同时把原始 JSON 中lyrics字段的换行信息保留了下来不会因为 CSV 转义问题丢掉空行。4. 在 ChineseLyrics 上跑通三个 NLP 任务情感、主题、生成拿到干净的歌词表后最值得先跑的三个任务是情感分析、主题建模和歌词生成。这三个任务分别对应自然语言处理里的分类、无监督聚类和序列生成也正好覆盖了歌词数据集的三种典型用法。4.1 歌词情感分析词典冷启动加 SnowNLP 基线阈值要按句调歌词情感分析和评论情感分析有个明显差别歌词很少直接说“我很伤心”而是用“雨下整夜”“落叶堆积了好几层”这类意象表达。所以纯深度学习模型在小样本上容易过拟合先用情感词典做冷启动再跑一个 SnowNLP 分数作为基线。import pandas as pd import re from snownlp import SnowNLP df_lines pd.read_parquet(lyrics_lines.parquet) positive_words set(爱 幸福 拥抱 彩虹 微笑 治愈 希望 温柔.split()) negative_words set(哭 眼泪 孤独 寂寞 分手 离开 伤害 黑夜 绝望.split()) def rule_sentiment(line): p sum(1 for w in positive_words if w in line) n sum(1 for w in negative_words if w in line) if p n 0: return 0.5 return round(p / (p n), 2) def snownlp_sentiment(line): try: return SnowNLP(line).sentiments # 0~1 之间越接近 1 越正面 except Exception: return 0.5 results [] for _, row in df_lines.head(2000).iterrows(): line row[line] rule_score rule_sentiment(line) sn_score snownlp_sentiment(line) results.append((row[song], line, rule_score, sn_score)) result_df pd.DataFrame(results, columns[song, line, rule, snownlp])说明rule_sentiment是我自己定义的一个极简规则。它把命中正向词和负向词的次数做比值没有命中就返回 0.5表示中性。这里的positive_words和negative_words需要根据 ChineseLyrics 的具体词频扩展我通常先从训练集里抽 50 首歌统计高频词再把明显带情感色彩的词加进这两个集合。SnowNLP(line).sentiments返回一个 0 到 1 的小数。实际跑下来歌词里的“伤感”往往被预测成 0.6 偏正向原因是 SnowNLP 的模型训练语料偏向购物评论“温暖”“怀抱”在购物评论里都偏正向。所以阈值要按句调整如果目标是把歌词分成“消极/中性/积极”三类我会把0.35视为消极0.65视为积极其他地方算中性比默认的 0.5 单阈值更稳。4.2 主题建模TF-IDF 加 LDA困惑度只做参考看主题词分布歌词主题建模的目标是看“这个歌手的歌里常出现哪些主题”比如爱情、成长、孤独、励志。LDA 是经典做法但对中文歌词很不友好因为歌词句子短、词共现弱、单字词多。所以我先做两件事用 jieba 分词然后过滤掉停用词和长度小于 2 的词。import jieba from gensim.corpora.dictionary import Dictionary from gensim.models.ldamodel import LdaModel lyric_stopwords set(的 了 我 你 他 她 它 我们 你们 就 也 都 在 是 啊 哦 啦 呀 吧.split()) def tokenize_lyric(text): words jieba.lcut(text) # 过滤停用词、单字词、纯数字 return [w for w in words if w not in lyric_stopwords and len(w) 2 and not w.isdigit()] df[tokens] df[lyrics].apply(tokenize_lyric) # 去掉整首只分出一个词的垃圾样本 df df[df[tokens].map(len) 5].reset_index(dropTrue) dictionary Dictionary(df[tokens]) corpus [dictionary.doc2bow(tokens) for tokens in df[tokens]] lda LdaModel(corpus, num_topics8, id2worddictionary, passes20, alphaauto, random_state42) for topic_id in range(8): words lda.show_topic(topic_id, topn10) print(topic_id, [w for w, _ in words])说明num_topics8这个参数要看语料规模。几万首歌词用 8 个主题比较合适太小会把“爱情”和“失恋”合并太大则出现大量重复主题。passes20是训练轮数歌词语料短20 轮足够过高的 passes 对短文本几乎没有增益。alphaauto让模型自己学习文档主题分布的稀疏度比固定值在歌词主题重叠高的场景下效果好。show_topic打印出来的主题词是概率分布的降序列表。不要只盯着困惑度曲线调num_topics我见过困惑度很低但主题词全是“我 的 心 爱”这种情况。歌词数据集的正确调参方式是打印每个主题前 10 个词人工看一眼能不能命名成“情感”“励志”“古风”。能命名的数量越多参数越合适。4.3 歌词生成字符级 n-gram让“作词机”落地真正从 ChineseLyrics 学歌词生成不用一上来就上 LSTM 或 Transformer。字符级 n-gram 是性价比最高的基线它可解释、训练快、还能直接看到押韵效果。下面的代码用训练集里所有按行切分的歌词构建一个三字符转移表。import random from collections import defaultdict df_lines pd.read_parquet(lyrics_lines.parquet) transitions defaultdict(list) for line in df_lines[line]: text line.replace( , ) if len(text) 4: continue # 用三个连续字符建立 n-gram 转移n3 for i in range(len(text) - 2): key text[i:i2] next_char text[i2] transitions[key].append(next_char) def generate_lyric(start_chars, max_len30, random_seedNone): rng random.Random(random_seed) if start_chars not in transitions: start_chars rng.choice(list(transitions.keys())) current start_chars output [current] for _ in range(max_len - 1): candidates transitions[current] if not candidates: break next_char rng.choice(candidates) output.append(next_char) current current[1:] next_char return .join(output) print(generate_lyric(回忆, max_len20, random_seed1))说明transitions是一个字典键是前两个字符值是候选下一个字符列表。每次从转移表里随机抽一个字符再更新 key。max_len30限制输出长度避免模型在一个循环里出不来。random_seed用来控制复现调试时固定种子能看出同样的输入是否稳定生成合理歌词。这个生成器有两个限制需要注意。第一它不会自动押韵。要押韵可以单独统计“韵脚字符”表生成最后一个字时强制从同韵候选里选。第二它很容易生成“的”“了”结尾的句子。所以训练前要把行级文件里句末是虚词的行做特殊处理或者切分时要求末字是实词。5. 避坑指南中文歌词数据集的 5 个高频问题这部分总结了我在 ChineseLyrics 上反复踩过的坑。每一条都是“现象、原因、解决”三步可以直接对照你跑实验时遇到的问题。5.1 现象一繁体歌词训练出来的模型在简体评论上完全失效用 ChineseLyrics 原始数据直接训练情感分类器在繁体歌词上准确率还行一旦输入简体评论文本准确率掉 20 个百分点。原因是有大量繁体汉字在分词阶段被当成未知词丢掉了“我爱你”转成“我愛你”后分词器可能切成“我”“愛”“你”情感词变成分裂字。解决方法是原始文本统一过 OpenCC 的t2s转换转换时保留粤语特有字。注意t2s并不是把所有字都转成简体“冇、嘅、唔”这些粤语字本来就只是汉字的一部分不用转。校验办法转换后随机抽 200 行歌词人工确认没有“愛、妳、説、裏”这类常见繁体残留。5.2 现象二副歌重复导致生成模型变成复读机运行第 4.3 节的 n-gram 生成器输出经常是“你是我最爱的唯一你是我最爱的唯一”。原因是歌词里副歌整段重复转移表中同一个二元组后面跟的字符高度集中模型很容易走进循环。解决方法是建立副歌去重按连续 4 行切段对每段做哈希如果同歌内出现相同哈希只保留第一次出现的段。注意不要把主歌里相似但不完全相同的段落误删阈值建议用“哈希完全相同且行数一致”而不是相似度阈值。5.3 现象三英文和拼音行污染分词结果清洗后仍存在类似“Yeah yeah yeah 你是我的 baby”的行。[u4e00-u9fff]过滤只保留中文字符会把这行变成“你是我的”但问题在于很多中文歌副歌会混大量英文词“Baby”这个词在情感分析里其实是正向情感词直接删掉会丢信息。解决方法是做双语分离包含英文单词的行单独存到lyrics_mixed表包含中文行存到lyrics_zh表分词时对混合行用混合模式。如果你只想做中文任务lyrics_zh就是干净数据如果想做中英混合理解再合并回去。5.4 现象四按句切分后歌名和歌手标签被丢光歌词按句切分以后很多人只保留了line文本和label歌手字段不要了。等到想按歌手做交叉验证才发现无法恢复“这一句属于哪首歌”。解决方法是切分时把song、singer、album一并带进行级表。前面第 3.4 节我建议的lyrics_lines.parquet已经带了这三个字段后续做情感分析要用歌手分组时直接groupby(singer)就行。如果已经丢掉了只能回到原始 JSON 用歌曲名重新 join 回来。5.5 现象五LDA 主题全是“爱”“的”“我”看不到语义跑第 4.2 节的主题模型打印出来的主题词是“爱、的、我、你、在、了”这类高频虚词。原因是歌词文本太短分词后单字词占比很高默认的停用词表又没有中文歌词中的“你、我、的”。解决方法是先统计全语料的词频把排名前 30 且没有实际语义的高频词加入lyric_stopwords同时把分词模式改成精确搜索不用全模式。单字词只保留有实义的比如“爱”“伤”“梦”其他直接过滤。调参后如果主题词还是“爱情、难过、分手”说明num_topics太小主题重叠太严重把num_topics调大两三个再看。6. 把 ChineseLyrics 当领域验证集小样本微调与输出校验习惯数据清洗到这可能已经花掉半天时间。我的建议是把这套清洗后的 ChineseLyrics 固定成一个“领域校验集”不要每次都重新洗。具体做法从训练集里抽出 100 首歌按句切成 1000 条测试样本给每条打上“情感极性”和“歌手风格”两个标注存成一个eval_lyrics.jsonl。以后不管是调大语言模型的 prompt还是训练小模型都拿这个固定集跑一遍。相比通用评测集它能很快看出模型有没有学歪比如“伤感的歌词是不是被预测成搞笑”。我习惯在每次微调后打印 20 条预测失败的真实歌词而不是只看准确率。歌词数据集的错误往往很有迷惑性模型预测“孤独”标签预测成“治愈”写完代码你根本想不到它看了哪句歌词。把失败样本揉成一句话你会发现大多是“我一个人吃饭旅行到处走走停停”这种既孤独又治愈的双关句。这种句子是歌词数据的常态不是清洗能解决的问题你要做的是把标签定义得更二值化或者干脆增加一个“复杂情感”类别。最后一个建议是不要清洗掉所有“不规则歌词”。把无意义的“啦”删掉没问题但口语化的“不要那么霸道”和古风词“一盏离愁”都是模型需要学习的真实表达。清洗的目标是去重复和去格式噪声不是把歌词变成新闻腔。我用这个原则在 ChineseLyrics 上跑过歌单推荐和歌词生成至少能稳定复现也少加班。希望帮到你。本文还有配套的精品资源点击获取
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。