我从高三开始就使用洛雪音乐助手来听歌,它已经成为了我使用时长第二长的软件(仅次于Google Chrome),基本上是只要打开电脑/手机就会打开它。这个软件非常好用,无论是什么歌,只要国内能听,就都能在里面找到;就是缺少了像其余音乐软件一样的统计功能。虽然我是洛雪音乐助手的contributor之一,但我无意改代码加入这个功能,而是使用lxmusic的缓存数据来自己进行统计。
曾经的歌词统计
早在我开始用lxmusic之前的高中时期,我就分析过网易云音乐的歌词缓存文件,且进行分词、计算词频,见马尔可夫链生成随机文本一文的最后部分;其中使用的中文分词工具是我初中时看Matrix67的博客写的fenci。在去年的年末,我也对洛雪音乐的“歌词缓存文件”(~/.config/lx-music-desktop/lyrics.json
)进行了类似的处理,下图是当时得到的词频统计结果:
我前几天想要搜索一句歌词的时候,怎么都搜不到,才发现这个“歌词缓存文件”的最后修改时间是2022年12月30日$\dots$看来上面的这个统计结果只能反映2022年及之前的洛雪音乐歌词,而2023年以后的歌词是保存在别的地方的。
现在的歌词统计
读取数据库
由于洛雪音乐助手是开源软件,很简单就能找到新版本lxmusic的歌词处理代码,在src/main/worker/dbService/modules/lyric/statements.ts:
export const createLyricQueryStatement = () => {
const db = getDB()
return db.prepare<[string]>(`
SELECT "type", "text", "source"
FROM "main"."lyric"
WHERE "id"=?
`)
}
可以看到目前的歌词保存在SQL数据库中,并且查询命令已经是现成的了;这个数据库文件的位置也很容易找到,比如Linux系统下路径为~/.config/lx-music-desktop/LxDatas/lx.data.db
。下面就只需读取这个数据库,执行上面的这条SQL,就能得到歌词数据了。
我选择使用Python完成这一任务。虽然我完全不知道如何读取SQL数据库,但是万能的Google一下子就帮我解决了:
import sqlite3
c=sqlite3.connect('lx.data.db').cursor()
l=c.execute('SELECT "type","text","source" FROM "main"."lyric"').fetchall()
观察得到的结果后发现"text"
项的值就是base64编码过的歌词;于是还需要进行base64解码。虽然我也完全不知道Python如何base64解码,但是万能的Google一下子就帮我解决了:
import base64
s="".join(base64.b64decode(v[1]).decode() for v in l)
s
就是得到的歌词字符串,我选择将其保存为文本来进行进一步的处理。
过滤为纯文本
目前得到的歌词文本看起来是这样的:
这<1560,750>世<2310,560>界[kuwo:067]\n[ver:v1.0]\n[ti:时光]\n[ar:许巍]\n
相比于我们认识中的“歌词文本”,这个文本多出了很多形如<...>
和[...]
的内容。我使用vim编辑歌词文本,:%s/<[^>]*>//g
和:%s/\[[^\]]*\]//g
这两条指令就能将<...>
和[...]
全部去掉。但是还有一些包含歌词题目及“作词”“作曲”“编曲”等信息的行,这些行并不属于歌词,可以使用:g/[::-]/d
去掉。
分词+词频统计
我参考CSDN上的Python中文分词、词频统计并制作词云图一文,使用jieba
模块进行了中文分词;它的效果当然是比我自己写的分词程序要好的,而且也支持各种编码,不需要再用wine跑我的Windows版本的程序了。
先读取过滤后的歌词文本,存入字符串txt
。然后
import jieba
words=jieba.cut(txt)
于是words
里存的就是分词结果了。我们需要剔除其中的日语罗马字、汉语拼音、英语等稀奇古怪的内容,并且仅保留长度为2以上的词。虽然我连Python如何写正则都完全不知道,但是万能的Google一下子就帮我解决了:
import re
from collections import Counter
s=re.compile('[a-zA-Z]*')
result=Counter(w for w in words if len(w)>=2 and not s.fullmatch(w)).most_common(50)
这样就得出了2023年开始我听的歌的歌词的词频统计结果。我将其与2022年及之前的统计结果对比,发现“青春”“欣赏”“黄昏”“温柔”等词有显著减少,而“自由”“等待”“温暖”的词频增加了许多。
制作词云
仍然是参考那篇CSDN文章,我使用了wordcloud
模块来制作词云。这个模块居然需要给定字体文件,开始时我还很疑惑为何需要这么底层的信息;直到看到输出结果我才明白,不同文字之间相互穿插而不遮挡,这是必须了解字体信息才能实现的。
from wordcloud import WordCloud
wc=WordCloud(font_path='FONT_FILE_PATH', background_color='white',width=1000,height=600)
wc.generate_from_frequencies(dict(result))
wc.to_file("result.png")
既然要使用字体文件,我第一个想到的就是我的手写字体:新字体,这个字体的诞生故事见高三文化课学习周记 Part 3的寒假部分。我也制作了使用Wen Quan Yi Micro Hei字体的版本。
成果展示: