开源工具软件XMusicDownloader——音乐下载神器
XMusicDownloader,一款 支持从百度、网易、qq和酷狗等音乐网站搜索并下载歌曲的程序。
缘起:
一直用网易音乐听歌,但是诸如李健、周杰伦的不少歌曲,网易都没有版权,要从QQ等音乐去下载,因此一直想写一个小程序,可以从其他音乐网站下载相关歌曲,趁放假,花了几小时做了这样一个程序。
BTW: 之前写过一个从酷狗和网易音乐提取缓存文件的程序,感兴趣的可以查看。
功能
- 聚合搜索多家音乐网站
- 支持音乐批量下载
- 搜索结果综合排序
- 可以编写Provider程序,支持其他音乐网站
实现IMusicProvider即可,主要是搜索和获取下载链接的方法。
public interface IMusicProvider
{
string Name { get; }
string getDownloadUrl(Song song);
List<Song> SearchSongs(string keyword, int page, int pageSize);
}
界面截图

下载程序
https://github.com/jadepeng/XMusicDownloader/releases
实现方案介绍
定义song实体
public class Song
{
public string id { get; set; }
public string name { get; set; }
public string singer { get; set; }
public string album { get; set; }
public string source { get; set; }
public double duration { get; set; }
public double size { get; set; }
public string url { get; set; }
public int rate { get; set; }
public int index { get; set; }
public string getFileName()
{
return singer + "-" + name + ".mp3";
}
public string getMergedKey()
{
return singer.Replace(" ", "") + name.Replace(" ", "");
}
}
封装各个音乐网站
抽象为MusicProvider,音乐提供方:),定义Name为名称,SearchSongs搜索歌曲,getDownloadUrl获取音乐下载地址。
public interface IMusicProvider
{
string Name { get; }
string getDownloadUrl(Song song);
List<Song> SearchSongs(string keyword, int page, int pageSize);
}
然后就是依次实现百度、网易等音乐网站,以QQ为例。
public class QQProvider : IMusicProvider
{
static HttpConfig DEFAULT_CONFIG = new HttpConfig
{
Referer = "http://m.y.qq.com",
};
public string Name { get; } = "QQ";
static string[] prefixes = new string[] { "M800", "M500", "C400" };
public List<Song> SearchSongs(string keyword,int page,int pageSize)
{
var searchResult = HttpHelper.GET(string.Format("http://c.y.qq.com/soso/fcgi-bin/search_for_qq_cp?w={0}&format=json&p={1}&n={2}", keyword, page,pageSize), DEFAULT_CONFIG);
var searchResultJson = JsonParser.Deserialize(searchResult).data.song;
var result = new List<Song>();
var index = 1;
foreach(var songItem in searchResultJson.list)
{
var song = new Song
{
id = songItem["songmid"],
name = songItem["songname"],
album = songItem["albumname"],
rate = 128,
size = songItem["size128"],
source = Name,
index = index++,
duration = songItem["interval"]
};
song.singer = "";
foreach (var ar in songItem["singer"])
{
song.singer += ar["name"] + " ";
}
result.Add(song);
}
return result;
}
public string getDownloadUrl(Song song)
{
var guid = new Random().Next(1000000000, 2000000000);
var key = JsonParser.Deserialize(HttpHelper.GET(string.Format("http://base.music.qq.com/fcgi-bin/fcg_musicexpress.fcg?guid={0}&format=json&json=3",guid), DEFAULT_CONFIG)).key;
foreach(var prefix in prefixes)
{
var musicUrl = string.Format("http://dl.stream.qqmusic.qq.com/{0}{1}.mp3?vkey={2}&guid={3}&fromtag=1", prefix, song.id, key, guid);
if (HttpHelper.GetUrlContentLength(musicUrl) > 0)
{
return musicUrl;
}
}
return null;
}
}
- 搜索调用
http://c.y.qq.com/soso/fcgi-bin/search_for_qq_cp?w={0}&format=json&p={1}&n={2}接口,获取下载地址调用http://base.music.qq.com/fcgi-bin/fcg_musicexpress.fcg?guid={0}&format=json&json=3,然后再组合。
聚合搜索
设计一个MusicProviders,加载所有的IMusicProvider,提供一个SearchSongs方法,并发调用各个网站的搜索,然后merge到一起。
public List<MergedSong> SearchSongs(string keyword, int page, int pageSize)
{
var songs = new List<Song>();
Providers.AsParallel().ForAll(provider =>
{
var currentSongs = provider.SearchSongs(keyword, page, pageSize);
songs.AddRange(currentSongs);
});
// merge
return songs.GroupBy(s => s.getMergedKey()).Select(g => new MergedSong(g.ToList())).OrderByDescending(s => s.score).ToList();
}
关于merge,核心就是将相同的歌曲合并到一起,我们暂且认为歌手+歌曲名相同的为同一首歌曲:
public string getMergedKey()
{
return singer.Replace(" ", "") + name.Replace(" ", "");
}
因此按megekey分组,就能实现聚合。我们设计一个MergedSong来包裹。
public class MergedSong
{
public List<Song> items
{
get; set;
}
public MergedSong(List<Song> items)
{
this.items = items;
}
public string name
{
get
{
return this.items[0].name;
}
}
public string singer
{
get
{
return this.items[0].singer;
}
}
public string album
{
get
{
return this.items[0].album;
}
}
public string source
{
get
{
return string.Join(",", this.items.Select(i => i.source).ToArray());
}
}
public double duration
{
get
{
return this.items[0].duration;
}
}
public double size
{
get
{
return this.items[0].size;
}
}
public double rate
{
get
{
return this.items[0].rate;
}
}
public double score
{
get
{
// 投票+排序加权 (各50%)
return this.items.Count / (MusicProviders.Instance.Providers.Count - 1) + (20 - this.items.Average(i => i.index)) / 20;
}
}
}
MergedSong的核心是定义了一个score,我们通过投票+搜索结果排序,用来决定合并结果的排序。
下载
下载主要是通过provider获取真实url,然后下载即可。
public class SongItemDownloader
{
MusicProviders musicProviders;
string target;
MergedSong song;
public event DownloadFinishEvent DownloadFinish;
public SongItemDownloader(MusicProviders musicProviders, string target, MergedSong song)
{
this.musicProviders = musicProviders;
this.target = target;
this.song = song;
}
public long totalBytes;
public long bytesReceived;
public double ReceiveProgress;
public double receiveSpeed;
DateTime lastTime = DateTime.Now;
public void Download()
{
WebClient client = new WebClient();
client.DownloadProgressChanged += Client_DownloadProgressChanged;
new Thread(() =>
{
// 多来源,防止单个来源出错
foreach (var item in song.items)
{
try
{
client.DownloadFile(musicProviders.getDownloadUrl(item), target + "\\" + item.getFileName());
DownloadFinish?.Invoke(this, this);
break;
}
catch
{
}
}
}).Start();
}
private void Client_DownloadProgressChanged(object sender, DownloadEventArgs e)
{
this.bytesReceived = e.bytesReceived;
this.totalBytes = e.totalBytes;
this.receiveSpeed = e.receiveSpeed;
this.ReceiveProgress = e.ReceiveProgress;
}
}
参考
- 程序界面,使用了https://github.com/Gsangu/KugouDownloader代码
- 搜索和下载方案参考 https://github.com/0xHJK/music-dl
作者:Jadepeng
出处:jqpeng的技术记事本--http://www.cnblogs.com/xiaoqi
您的支持是对博主最大的鼓励,感谢您的认真阅读。
本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
开源工具软件XMusicDownloader——音乐下载神器的更多相关文章
- 开源音乐下载神器XMusicDownloader更新,支持歌单一键下载,支持无损音乐
开源音乐下载神器XMusicDownloader更新啦,新增网易.腾讯音乐歌单歌曲.歌手歌曲.专辑歌曲一键下载,同时支持下载flac无损音乐. 功能 V1.0 功能开源工具软件XMusicDownlo ...
- NSA开发的工控ICS/SCADA态势感知开源工具Grassmarlin(附下载地址)
工具简介 GRASSMARLIN是一款由美国国家安全局开发的,能够帮助运维工程师在IP网络上发现并编目监控和数据采集系统(SCADA)和工业控制系统(ICS)主机的开源软件工具,也被称为被动网络映射器 ...
- 10款 Mac 系统优化清理工具软件推荐和下载
本文内容及图片来源[风云社区 SCOEE] 在Windows上有各种安全卫士.系统助手等系统优化和清理工具,比如360安全卫士.腾讯安全管家等,同样MacOS系统也有很多好用的系统优化清理工具,体验比 ...
- 「下载神器」aria2 懒人安装教程 [Windows]
是一款开源.轻量级的多协议命令行下载工具,支持 HTTP/HTTPS.FTP.SFTP.BitTorrent 和 Metalink 协议,拥有众多第三方支持插件,被誉为「下一代下载工具」和「下载神器」 ...
- 开源一个自动整理B站UWP客户端软件进行批量下载的视频文件的小工具BiliVideosReoganizeHelper
大家都知道B站是一个很受欢迎的视频学习网站,上面有很多无私的up主上传了大量优秀的教学视频,在此向B站致敬,向广大UP主致敬. 有时,我们需要下载收藏一些视频,以防止以后找不到了.那么我们可以用B ...
- BAT等大厂已开源的70个实用工具盘点(附下载地址)
前面的一篇文章<微软.谷歌.亚马逊.Facebook等硅谷大厂91个开源软件盘点(附下载地址)>列举了国外8个互联网公司(包括微软.Google.亚马逊.IBM.Facebook.Twit ...
- puppet开源的软件自动化配置和部署工具——本质就是CS,服务端统一管理配置
1. 概述 puppet是一个开源的软件自动化配置和部署工具,它使用简单且功能强大,正得到了越来越多地关注,现在很多大型IT公司均在使用puppet对集群中的软件进行管理和部署,如google利用p ...
- Debian 安装下载工具软件
Debian 安装下载工具软件 1.下载BT种子Torrent文件 Linux下载种子文件肯定不能使用迅雷了,推荐一款叫做qBittorrent的P2P下载软件,目前在Ubuntu中使用很广泛,同样D ...
- 精品工具【音乐下载器(可下载VIP音乐)】
工具信息 更新时间:2020年5月26日00点07分更新内容:1. 增加快捷键2. 细分下载列表清除功能一款可以下载付费音乐的音乐下载器 下载链接:https://nitian1207.lanzous ...
随机推荐
- 修改svn默认端口
Subversion有两种不同的配置方式,一种基于它自带的轻量级服务器svnserve,一种基于非常流行的Web服务器Apache. 根据不同的配置方式,Subversion使用不同的端口对外提供服务 ...
- Find Lines
(Uva 6955可以直接随机,湖大OJ 13348 要优化) 题意:给出 n个点的坐标, 一个 百分数p, 求是否有一条直线上有 n * p /100个点… 随机化算法,但也要优化下……(TLE, ...
- Mysql 的安装(压缩文件)和基本管理
MySql安装和基本管理 本节掌握内容: mysql的安装.启动 mysql破解密码 统一字符编码 MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,目前属于 Oracle ...
- 【原创】Linux基础之命令行浏览器links
有时服务器环境受限,比如在内网环境不能暴露端口从外网访问,用curl看html代码比较累,这时可以使用命令行浏览器来查看相关页面 links 官方:http://links.twibright.com ...
- [C]关于extern与struct
问题 我曾经很困惑,就是在两个编译单元当中,如何把一个单元中声明的struct结构引入到另外一个单元中来,折腾了很久,后来发现这位大神的留言 不是这么用的…… 类型的定义和类型变量的定义不同,类型定义 ...
- 13)django-ORM(连表一对多,外键创建,创建数据,3种查询)
一对多需要使用外键 一:外键创建ForeignKey b=models.ForeignKey(to="Business",to_field=("id"))#dj ...
- vue 上实现无缝滚动播放文字系统公告
首先实现效果,当时的需求做的系统公告框设定一个宽度,超宽滚动播放,没超宽则静态展示,有了需求,想了下实现原理,最开始打算js更改字体内容的方式,但是想了下感觉会有点麻烦,想起之前做了表格的左侧边固定, ...
- 微信小程序UI组件--Lin UI
地址:http://doc.mini.7yue.pro/ Lin UI 是基于 微信小程序原生语法 实现的组件库
- 判断js数据类型的四种方法,以及各自的优缺点(转)
转载地址:https://blog.csdn.net/lhjuejiang/article/details/79623973 数据类型分为基本类型和引用类型: 基本类型:String.Number.B ...
- 【shell】两种字符串提取场景的实现
shell虽然比batch顺眼点儿,但还是老话,入门容易,精通难. 1.场景一是这样的,现有字符串的内容 name: tiger; age:18; location:china; 需求:提取每个属性的 ...