LrcEditor开发记(一)api接口
前言
项目地址:Github
前一段时间将我写的歌词编辑器 LRCEditor
完善了一下,添加了一个搜索歌词的功能,但是仅限于网易云(因为网易云音乐的API是最好搞的),有一些网易云上面没有版权的歌曲自然就搜不到歌词,非常影响体验
于是就想到将另外两家音乐软件:QQ音乐和酷狗音乐的 API 也搞过来,添加到搜索功能里面去,这样基本上就不用担心搜不到歌词了:)
然后就花了整整一天时间研究他们的 API……
这里将 QQ 音乐和酷狗音乐的 API 接口使用整理一下,看到这篇文章并且有需要的小伙伴就可以直接拿去用了:)
P.S.1 整理的时间是 2020 年 2 月,有些接口过了一段时间可能就被更换了,所以看完还请自己先验证一波……
P.S.2 本文中接口网址返回的数据均为 JSON 字符串
P.S.3 有关网易云接口的整理在另一篇博文里,链接:VB.NET | 在线获取歌词方法的小小总结
1. QQ 音乐部分
搜索歌曲
网址格式:https://c.y.qq.com/soso/fcgi-bin/client_search_cp?aggr=1&cr=1&flag_qc=0&p={0}&n=20&w={1}
参数说明:
p={0}
表示返回搜索结果中的第几页,和n=20
一起用n=20
每页返回的结果数量w={1}
要搜索的关键字
调用例子:https://c.y.qq.com/soso/fcgi-bin/client_search_cp?aggr=1&cr=1&flag_qc=0&p=1&n=20&w=Faded
这一步可以获取歌曲的一些基本信息(名字,艺术家,专辑,时长等),同时需要在返回的信息里面获取歌曲的 mid
,接下来获取歌词,封面图片,播放的文件都要用到
获取歌词
这一个接口网址好像没有人介绍过???就是直接打开QQ音乐(网页版)的播放界面,然后F12,在Network 里面筛选XHR格式且含有 Lyric 关键词的文件,就会发现有一个文件是指向这个网址的
网址格式:https://c.y.qq.com/lyric/fcgi-bin/fcg_query_lyric_new.fcg?-=MusicJsonCallback_lrc&songmid={0}&g_tk=758816886&format=json&inCharset=utf8&outCharset=utf-8¬ice=0&platform=yqq.json&needNewCode=0
参数说明:
songmid={0}
表示上一步中获取到的歌曲mid
值
调用例子:https://c.y.qq.com/lyric/fcgi-bin/fcg_query_lyric_new.fcg?-=MusicJsonCallback_lrc&songmid=004QK3K60anL4V&g_tk=758816886&format=json&inCharset=utf8&outCharset=utf-8¬ice=0&platform=yqq.json&needNewCode=0
然后,你会发现返回的是:
1 | {"retcode":-1310,"code":-1310,"subcode":-1310} |
别慌,这是 QQ 音乐防止爬取数据而设置的障碍,我们只需要在 Request 里面设置两个东西:
Referer = https://y.qq.com/portal/player.html
skey = ......
第二个 skey
每次访问都是会变化的,但是服务器不会检测它的正确性,所以直接拿浏览器访问一次之后把 skey
放到代码中即可
然后就可以正常访问了,用 C# 实现的代码如下:
1 | HttpWebRequest req = (HttpWebRequest)WebRequest.Create("https://c.y.qq.com/lyric/fcgi-bin/fcg_query_lyric_new.fcg?-=MusicJsonCallback_lrc&songmid={0}&g_tk=758816886&format=json&inCharset=utf8&outCharset=utf-8¬ice=0&platform=yqq.json&needNewCode=0"); |
然而,你会发现,返回的字符串是这个样子的:
1 | "W3RpOkxBU1QgU1RBUkRVU1QgKOOAikZhdGUvc3RheSBuaWdodCAoVW5saW1pdGVkIEJsYWRlIFdvcmtzKeOAi1RW5Yqo55S75o+S5puyKV0KW2FyOkFpbWVyICjjgqjjg6EpXQpbYWw6REFXTiAo6buO5piOKV0KW2J5Ol0KW29mZnNldDowXQpba2FuYToxMTExMeOBlzHjgY3jgofjgY8x44Go44GzMeOBquOBhDHjgb7jgZUx44Gy44KNMeOBpOOCiDHjgYLjgoEx44GI44GMMeOChjHjgoEx44GvMeOBteOCizHjgYvjgZ8x44GsMeOBguOCizHjgaTjgaUx44GZMeOBjTHjgaHjgYQx44GmMeOBmeOBjTHjgb4x44GGMeOBhOOCjTHjgY0x44GNMeOBiuOBjzHjgbLjgo0x44GC44GkMeOBhOOBqDHjg .....(后面很多很多就不放出来了)" |
也不要慌,这个一长串明显是 Base64 加密处理过的,我们只需要一下就能把它还原成本来的样子:
1 | string new_lyric = Encoding.UTF8.GetString(Convert.FromBase64String(lyric)); |
获取专辑的封面
网址格式:http://imgcache.qq.com/music/photo/album_500/17/500_albumpic_{0}_0.jpg
参数说明:
500_albumpic_{0}_0.jpg
在{0}
处填上第一步获取的专辑mid
值(不是歌曲mid
)
调用例子:http://imgcache.qq.com/music/photo/album_500/17/500_albumpic_8217_0.jpg
这个网址打开了是 500×500 的封面图,如果想要自定义大小,把地址中两个 500 都改成对应的大小即可
获取可以播放的文件
这一步比较复杂,如果不是控制台程序建议弄成异步
获取文件,要先获取它的 Token(就是一种类似于通行证的东西):
网址#1 格式:https://c.y.qq.com/base/fcgi-bin/fcg_music_express_mobile3.fcg?format=json205361747&platform=yqq&cid=205361747&songmid={0}&filename={1}&guid=126548448
参数说明:
songmid={0}
歌曲的mid
值filename={1}
由歌曲的mid
值拼接而来,filename = 'C400' + mid + '.m4a'
例如
mid
为004QK3K60anL4V
,文件名就是C400004QK3K60anL4V.m4a
调用例子:https://c.y.qq.com/base/fcgi-bin/fcg_music_express_mobile3.fcg?format=json205361747&platform=yqq&cid=205361747&songmid=004QK3K60anL4V&filename=C400004QK3K60anL4V.m4a&guid=126548448
另外的参数例如 cid
和 guid
都是可以写死的,所以就不用管了
在这一步的返回值里面可以看到 {"vkey" : "..."}
的字段,vkey
就是用来拼成获取播放文件的网址的东西
网址#2 格式:http://ws.stream.qqmusic.qq.com/{0}?fromtag=0&guid=126548448&vkey={1}
参数说明:
{0}
上一步提到的filename
,用歌曲mid
值加工而成vkey={1}
填刚刚得到的vkey
调用例子:http://ws.stream.qqmusic.qq.com/C400004QK3K60anL4V.m4a?fromtag=0&guid=126548448&vkey=...
(vkey很长就不写出来了)
打开网址就是一个 m4a 文件,大功告成!
2. 酷狗音乐部分
相比起 QQ 音乐,酷狗音乐的 API 接口的破解要简单一些
搜索歌曲
网址格式:http://mobilecdn.kugou.com/api/v3/search/song?format=json&keyword={1}&page={0}&pagesize=20&showtype=1
参数说明:
page
和pagesize
页数和每页返回的结果数量keyword
要搜索的关键字
调用例子:http://mobilecdn.kugou.com/api/v3/search/song?format=json&keyword=Faded&page=1&pagesize=20&showtype=1
这一步可以获取歌曲的一些基本信息(名字,艺术家,专辑,时长等),同时需要记录歌曲的 hash
值,接下来会用到
获取专辑封面,歌词,和播放文件
网址格式:https://www.kugou.com/yy/index.php?r=play/getdata&hash={0}
参数说明:
hash={0}
上一步得到的歌曲hash
值
调用例子:https://www.kugou.com/yy/index.php?r=play/getdata&hash=F139D898F1ED75CAD7B582BD1BAC0093
然后,你可能会发现,返回的是:
1 | {"status":0,"err_code":20010,"data":[]} |
如果不是这个结果,那么将浏览器的 Cookie
清除掉,刷新一下,就会是这个返回值
然而,如果用代码来直接访问的话,结果就一定会变成这样
但我们还是不慌,现在先输入酷狗官网的网址 www.kugou.com
,随便点进去听一首歌,再把这个网址输进去,你就会发现,返回值变得正常了
再看这个网址,他有 www.kugou.com
的前缀,也就是说,访问这个网址时,和访问官网时用的是同一批数据,问题肯定就出在这批数据上了,经过反复尝试,我发现是 Cookie
中的 一个 kg_mid
字段决定了返回值正常与否
关于这个字段,网上有专门计算的方法和程序:酷狗音乐网站前端JS的逆向破解过程,但是实际上我们并不需要每次访问时都计算一遍,就像刚才的 skey
,这个 kg_mid
也是属于有就行的那一类,服务器并不会检查它的正确性,所以还是浏览器访问一次,然后复制粘贴到代码当中即可:
1 | HttpWebRequest req = (HttpWebRequest)WebRequest.Create(new Uri(LInterface.KuGouMusic_Detail(QMid))); |
专辑封面,播放文件的网址和歌词都在返回值里面了,看英文就可以判断出来,于是酷狗的 API 接口破解成功!
但是,我们注意到酷狗 API 中返回的歌词是没有翻译的!!!不是中文歌搜没有翻译的歌词还有什么用,本着一条龙服务的原则,我决定再做一个 API 用来翻译……
3. Google翻译 API
这部分的大多数内容转载自:C#实现谷歌翻译API,不同的地方在于这篇文章用的是 www.translate.google.com
这个网址,现在已经访问不到了,不过我们还有 www.translate.google.cn
这个国内版的翻译网址,获取 API 的方式也基本一致
获取 TKK
打开 www.translate.google.cn
,随便输入点英文,然后 F12 打开看 Network,发现只有这个网址指向了翻译的结果:https://translate.google.cn/translate_a/single?client=webapp&sl=en&tl=zh-CN&hl=zh-CN&dt=at&dt=bd&dt=ex&dt=ld&dt=md&dt=qca&dt=rw&dt=rm&dt=ss&dt=t&source=bh&ssel=0&tsel=0&kc=1&tk=262549.177587&q=...
分析:注意到整个网址中只有 q=...
是我们输入的内容,sl
和 tl
分别是源语言和目标语言(sl
填 auto 就相当于自动检测语言了),其它的字段都是自动填好的
然后注意到一个重要的字段 tk=262549.177587
,注意到每次打开这个页面后,附带的 tk
都是不一样的,而且我们看不出什么规律
tk
嘛,就相当于 ticket
,票的意思,应该就是 Google 防止随意调用翻译 API 设置的障碍了
这个 tk
其实和两个东西有关,一个是我们输入的内容,另一个是隐藏在页面 HTML 文档中的 TKK
值,可认为,两者都是浮点数类型,那么有可能 tk
就是由 TKK
计算得到的
计算 tk
监视发现,网站中有一个 JS 调用了这个 TKK
并通过某种算法生成了 tk
,网上已经有人破解了这段算法的代码:
1 | var b = function (a, b) { |
代码中函数 tk(a,TKK)
的参数 a
是我们输入的内容,TKK
是刚才得到的值,直接调用 JS 代码就可以获得 tk
了
由于 ScriptControl
,C# 里面是可以直接调用 JS 代码的:
1 | MSScriptControl.ScriptControl scriptControl = new MSScriptControl.ScriptControl(); |
然后就可以正常的返回翻译结果了,注意重复调用时不用每次都先访问 www.translate.google.cn
获取 TKK
,只用获取一次,然后动态根据输入的内容生成 tk
即可
歌词API代码:Ubuntu Pastebin
翻译API代码:Ubuntu Pastebin(感谢C#实现谷歌翻译API)