时雨小径 May the Spirit be with you

新坑: 时雨

地址在此
欢迎把玩.

眼看着数据库里的歌的数据也有3万首了, 所以想玩点新花样出来.

第一个是想要实现按歌手搜索歌曲. 要做这个的前提是需要把歌手的信息稍微标准化一下, 在现在的数据库里, 只是在每首歌的记录下有一个歌手的名字, 然而这里会出现的情况就是一个歌手的名字可以有好几种形式, 最简单的一个例子就是简繁体, 一个'张国荣', 另外一首歌下面的记录是'張國榮', 会被识别成两个歌手. 直接的想法就是建立另外一个表, 里面储存所有歌手的信息, 使每一个歌手都被分配到一个单独的ID, 再利用这个ID与歌曲的记录关联起来. 这样一来也解决了一首歌有两个歌手的情况.

实现这一步的时候, 人肉/暴力是不能接受的, 没那么多精力. 所以呢, 首先设定的目标就是在一定的错误容许范围内尽量地产生可接受的数据, 之后可以在这个基础上人肉校对.

在这里利用了musicbrainz这个音乐数据库, 借用其提供的API, 可以通过名字搜索歌手, 这是一个XML结果例子:

 <artist id="d780609b-eca5-4277-a0c2-801cc0404764" type="Person" ext:score="100">
         <name>張國榮</name>
         <sort-name>Cheung, Leslie</sort-name>
         <gender>male</gender>
         <country>HK</country>
         <area id="0373cdff-eac8-3fbc-92dc-36a607da06d1">
            <name>Hong Kong</name>
            <sort-name>Hong Kong</sort-name>
         </area>
         <life-span>
            <begin>1956-09-12</begin>
            <end>2003-04-01</end>
            <ended>true</ended>
         </life-span>
         <alias-list>
            <alias sort-name="±i°êºa" type="Search hint">±i°êºa</alias>
            <alias locale="en" sort-name="Cheung, Leslie" type="Artist name" primary="primary">Leslie Cheung</alias>
            <alias sort-name="Zhang Guo Rong">Zhang Guo Rong</alias>
            <alias locale="zh_Hans" sort-name="张国荣" type="Artist name" primary="primary">张国荣</alias>
         </alias-list>
         <tag-list>
            <tag count="1">
               <name>chinese</name>
            </tag>
            <tag count="1">
               <name>cantonese</name>
            </tag>
         </tag-list>
      </artist>

其中包括了一个MBID, 就是这个数据库的为每个歌手分配的独一的ID, 并且可以看到在alias里可以找到该歌手其他形式的名字.
所以, 我在脚本里处理一个歌手的名字的过程就是:

  1. 调用musicbrainz的API, 传入歌手名字
  2. 在结果中寻找是否有匹配
  3. 如果在结果中找到匹配, 得到MBID, 在本地数据库歌手的表中中按MBID搜索, 如果已经有了, 则说明该歌手已经被记录, 如果没有, 则把歌手已经MBID添加到歌手的表里.
  4. 关于歌手头像, 我是用的LAST.FM的API, 还是挺好用的, 很多不知名小歌手的头像也能找到.

中间也有很多问题, 比如说同名歌手问题, 或者有些小众歌手没有被musicbrainz收录, 或者收录了但是Alias里提供的没有匹配到. 我觉得这个要靠脚本解决会把脚本写得很臭很长, 花在测试以及debug上的时间还不如我人肉去把歌手名字改一改, 所以花了一点功夫在考虑脚本过程中的如何产生log来方便之后的人肉校正, 比如说通过匹配Alias过程来为已有的歌手姓名提供一些"改名建议"以方便标准化脚本的运行, 目前看来这个决定还是明智的.

做了一个找相似歌手的功能, 比较粗糙, 用的算法还是以前的, 可以参考以前写的这个简单推荐系统算法.

然后是在播放资源上的一个"改进", 之前因为豆瓣防盗链的缘故, 会检查header里的referer, 如果不符合规则就会返回403, 因为Javascript不能实现修改header的功能, 所以之前的办法是利用chrome的插件来修改web request里的header来骗一下豆瓣的服务器, 但是这个, 总之还是觉得不够方便, 首先, 换个浏览器就听不了, 然后移动端用手机平板就听不了, 再者, 要demo给别人看的时候还非得让他用chrome再装个插件, 太不专业.

所以这次借着新坑顺便也把这个给解决了, 方法就是相当于把我的服务器当成一个代理来用, 在服务器上通过解析出来的URL读取豆瓣服务器上的文件, 同时把内容输出到前段.
其实有个很不厚道的想法, 现在美国这边CDN也便宜, 想租一个然后写个脚本把现在能拿到的资源都传到CDN上…这样就不用走博客所在服务器的流量了. 不过想想好像有点过分了, 便也作罢.

音乐播放器是用的SoundManager2, 这是个挺牛逼的库.

其实到目前为止, 做出来的都不是些能继续深入玩的东西. 我想做的其实是要更炫酷饥渴极客一点的.
我用的是MySQL, 在数据日益增多之后, 搜索的速度成了一个问题. 我也知道其实通过建立合理的表结构以及用好合适的SQL语句, 是能大大地优化速度的. 但是我想在这个项目里, 对于这样一种比较特定的关系结构已经询问的需求, 是不是可以用一种自定义的方法来建立索引以实现更好的搜索结果呢? 这个靠YY真的是很难有头绪, 这几天去看了数据库索引之类的基础知识, 主要是一些有关B树的论文.
想要设计一个针对音乐数据库的scalable的索引, 想想都是件很令人兴奋的事情呢.

最后声明一下: 以上及该项目纯粹为了个人学习研究目的. 再次感谢豆瓣的资源.

PS: 太久不写文章, 中文真的写不溜了, 尽量不夹英文单词真是别扭啊, 读者见谅. 我语文不是体育老师教的.. = =