实现自己的音乐搜索软件(一)

 

在公司上班,都用QQ音乐听歌,然后一天同事给了个网页听歌的。当然不是百度那些MP3搜索的。页面是一个播放器,边上一个搜索框,很方便。反正最经也不忙,想自己也来做个搜索歌曲的,输入歌名返回地址。毕竟去百度搜索还要多点几下,现在一下就搞定了。

 



一 实现思路

因为没有自己的音乐库,所以只能到网上去搜索。于是选择了百度和soso两个网站,利用WEB请求,对返回的结果进行分析,得到MP3地址。这就是最基本的实现思路。其实很简单,就是用到了.NET中HttpWebRequest类来操作,然后使用正则表达式分析返回的结果。

 

有了基本思路,就要调查如何实现。如何去网上搜索MP3。我们平时去百度搜索,在地址栏中可以看到URL中带有参数,我们可以通过构造一个URL,提交请求,获得页面的HTML。然后从中得到MP3以及歌词。

 

以下就是整理的搜索URL的格式。具体结果可以在IE中看到。其中百度和soso是返回和页面HTML,也就是我们在IE中看到的页面;而百度快搜是返回一个XML文件,最多只返回5首歌曲信息;最后是利用千千静听的歌词服务器,获得歌词信息,然后通过歌词信息中的内容,构建URL去获取歌词文件,返回的是LRC文件。

 

 

 

 

从上面可以看到,尽管搜索页面和类容不同,但是都是:构建URL--请求--分析页面--取得地址 。所以我们可以吧相同的部分提取出来作为一个基类。下图就是最开始的结构:

实现1 search

建立了一个BaseSearch的抽象基类,其中有一个PageRequest 的方法,他是对HttpWebRequest操作的包装,输入一个URL和编码方式,返回一个PageContext的流。然后是一个PageAnalysis 方法,这个方法是一个抽象方法,用来分析返回的页面流。不同的子类有不同的分析方法,所以具体分析算法,由子类自己重写。有点策略模式的感觉。

 

GetMusicList、GetMusicLrcList、GetMusicLyrics 三个方法是获得歌曲列表、歌词列表、歌词内容;他们都调用了PageRequestPageAnalysis 方法,并且实现了失败重试,超时等。向外提供查询的接口。

 

然后又建立了一个SearchInfo类,她的作用是创建不同的请求URL(图中的Create方法),然后提供3个子类的搜索方法,最后一个Search方法,接受搜索信息,返回MP3和歌词信息。最终用户能看到的就只有这个类中的Search方法。

 

 

当然还新建了其他一些辅助类,比如RegerHelper来包装对正则表达式的操作,CommonOperator来进行通用的操作,比如URL和HTML的编码解码;建立了歌曲信息,歌词信息,搜索信息对应的实体类,以及一些枚举对象,比如音乐格式,搜索类型。



二 实现的改进

上面的代码实现之后,倒是没有什么问题。不过既然是自己练习,就想做的扩展性更强,因为我们是对网页进行分析,网页是会变化的,而且可以搜索的网页也不仅仅是百度和搜搜。如果要增加一个新的搜索方式,必须继承BaseSearch,需要重新编译。所以想到把每个搜索方法编译成一个DLL,然后搜索时加载这些DLL。这样,当增加了新的搜索方法时,只需要新增一个DLL。

 

为了实现类似与插件的方式,我们就需要定义接口。而我们搜索方法,是对接口进行操作。

 

 

改进结构

 

上图就是改进后的结构。最右边定义了3个接口。IEncoding 是指定页面的编码方式;IMusicSearch 是进行音乐搜索时要实现的接口;ILRCSearch 是进行歌词搜索时要实现的接口。然后看看中间的4个类,他们就是实现了这些接口,实现了自己的搜索。

 

NetworkRequest 是对HttpWebRequest的包装。和之前的功能是一样的。只不过获取页面的编码是通过IEncoding接口获得的。


Crawler 是搜索的核心部分。GetMusicList、GetMusicLrcList、GetMusicLyrics 三个方法的作用没有变化,他们也是获取URL-请求-分析--返回结果。但是他们是对接口进行编程,例如搜索歌曲GetMusicList方法 的实现如下:

 

  1. 调用IMusicSearch 接口的CreateMusicUrl 方法获取URL
  2. 调用NetworkRequestPageRquest 方法请求URL,而编码方式是通过IEncoding 接口的PageEncode 取得。
  3. 调用IMusicSearch 接口的PageAnalysis 方法分析返回的页面流
  4. 返回歌曲信息。

 

MSLRCRunner 的作用是对客户端提供搜索接口。在前面我们把实现搜索接口的DLL放到了指定的Plugin目录下, Initialize方法就是来加载这些插件。然后对加载的插件调用Crawler 中的方法,得到结果。并向客户端提供SearchM和SearchL方法。这样对于新增的DLL,只需要放到Plugin就可以直接使用。

 



三 实现中的一些问题

因为没有自己的数据库,所以搜索都是通过网络,这也是的搜索速度是一个需要考虑的问题。目前从3个地方那个搜索歌曲信息。对于百度快搜返回5首歌曲,而其他2个搜索,都只是搜多第一页的内容。所以总体上速度还是很快的。考虑对每个DLL搜索时采用多线程。这样可以加快速度。

 

在每个具体搜索方法中,也是对网页中<TR></TR>块中信息进行分析。百度一页30条记录,搜搜一页20条记录。但是因为每条记录分析速度很快。所以并没有采用多线程,因为线程切换反而可能导致速度更慢。当然后来做成插件的形式,那就是自己决定了。

 

经过分析大部分的搜索时间花在了网络请求上,但是每次分析必须等请求完成后进行。所以考虑使用异步请求来提高速度。但是因为在请求和分析之间不需要什么操作。所以采用异步也没有真正的提升速度,只是释放了线程。在单机和小并发的情况下,还是采用简单的同步方式实现。如果作为服务器短,提供多人同时搜索,大并发下可以使用异步方式,及时释放线程,提高吞吐量。

 

如果作为server提供服务,也可以把搜索的结果保存到数据库中,这样就能加快搜索速度,并建立自己的搜索库。

 

最后有一个没有解决的问题:因为我是分析页面中的信息,从页面中获取地址等信息。而很多MP3搜索网站,页面上没有直接提供地址,而是通过一段JS来获得歌曲地址。不知道这个有没有办法实现。

 



四 Demo效果

 

demo

 

这就是TEST的DEMO,后面打算使用WPF来做界面,并增加播放器。不过下周开始新的项目事情很多,估计没什么时间了。而且要出差,所以不知道什么时候能搞定。这次就不放代码了,同事还在修改,下周吧。

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值