本文使用Java xpath 爬取某易云歌曲,并下载至本地。

代码仅用于个人学习使用,欢迎各位大佬提出建议。

1、添加依赖

        <dependency>
<groupId>cn.wanghaomiao</groupId>
<artifactId>JsoupXpath</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.9</version>
</dependency>

2、获取音乐id和url

    /**
* 获取歌曲信息
*
* @param url
* @return
*/
public Map<String, Object> getMusicInfo(String url) {
Map<String, Object> result = new HashMap<>();
url = url.replace("/#", "");
Map<String, Object> header = new HashMap<>();
header.put("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36");
header.put("Referer", "https://music.163.com/");
header.put("Host", "music.163.com");
String res = HttpUtil.get(url, header); JXDocument jxDocument = JXDocument.create(res);
//歌曲列表
List<JXNode> songs = jxDocument.selN("//ul[@class=\"f-hide\"]/li/a");
//歌单名称
JXNode jxsonglistName = jxDocument.selNOne("//h2[contains(@class,\"f-ff2\")]/text()");
//歌手名
JXNode jxsingerName = jxDocument.selNOne("//h2[@id=\"artist-name\"]/text()");
String songlistName = null != jxsonglistName ? jxsonglistName.toString() : "";
String singerName = null != jxsingerName ? jxsingerName.toString() : ""; System.out.println(String.format("=======================%s=======================", StrUtil.isBlank(songlistName) ? singerName : songlistName));
List<Map<String, Object>> musics = new ArrayList<>();
result.put("title", StrUtil.isBlank(songlistName) ? singerName : songlistName);
for (JXNode song : songs) {
Element element = song.asElement();
String songName = element.text();
String songId = element.attr("href").split("=")[1];
String songUrl = OUT_LINK + songId;
Map<String, Object> map = new HashMap<>();
map.put("songId", songId);
map.put("songName", songName);
map.put("songUrl", songUrl);
map.put("title", StrUtil.isBlank(songlistName) ? singerName : songlistName);
//map.put("lyric", getMusicLyric(songId));
musics.add(map);
//单线程下载歌曲
//downloadSong(songName, songUrl, result.get("title").toString());
}
musics.forEach(x -> System.out.println(x)); //多线程下载歌曲
//multiDownload(musics);
result.put("songs", musics);
//System.out.println(result);
return result;
}

3、获取歌词

    /**
* 获取歌词
*
* @param songId
* @return
*/
public String getMusicLyric(String songId) {
String url = String.format("http://music.163.com/api/song/lyric?id=%s&lv=-1&kv=-1&tv=-1", songId);
Map<String, Object> header = new HashMap<>();
header.put("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36");
header.put("Referer", "https://music.163.com/");
header.put("Host", "music.163.com");
String res = HttpUtil.get(url, header);
return JSONObject.parseObject(res).getJSONObject("lrc").getString("lyric");
}

4、完整代码

加入多线程下载歌曲代码

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.Console;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import org.jsoup.nodes.Element;
import org.seimicrawler.xpath.JXDocument;
import org.seimicrawler.xpath.JXNode; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; public class Music163 {
//下载地址
private static String OUT_LINK = "http://music.163.com/song/media/outer/url?id=";
//本地下载目录
private static String DOWNLOAD_PATH = "E:\\music\\"; public static void main(String[] args) {
String musicUrl;
//歌曲清单
// 热歌 3778678 原创 2884035 新歌 3779629 飙升 19723756
musicUrl = "https://music.163.com/#/playlist?id=3778678";
// 歌手歌曲榜单 8325->梁静茹
//musicUrl = "https://music.163.com/#/artist?id=8325";
//搜索列表
// musicUrl = "https://music.163.com/#/search/m/?order=hot&cat=全部&limit=435&offset=435&s=梁静茹";
Music163 music163 = new Music163();
music163.getMusicInfo(musicUrl);
} /**
* 获取歌曲信息
*
* @param url
* @return
*/
public Map<String, Object> getMusicInfo(String url) {
Map<String, Object> result = new HashMap<>();
url = url.replace("/#", "");
Map<String, Object> header = new HashMap<>();
header.put("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36");
header.put("Referer", "https://music.163.com/");
header.put("Host", "music.163.com");
String res = HttpUtil.get(url, header); JXDocument jxDocument = JXDocument.create(res);
//歌曲列表
List<JXNode> songs = jxDocument.selN("//ul[@class=\"f-hide\"]/li/a");
//歌单名称
JXNode jxsonglistName = jxDocument.selNOne("//h2[contains(@class,\"f-ff2\")]/text()");
//歌手名
JXNode jxsingerName = jxDocument.selNOne("//h2[@id=\"artist-name\"]/text()");
String songlistName = null != jxsonglistName ? jxsonglistName.toString() : "";
String singerName = null != jxsingerName ? jxsingerName.toString() : ""; System.out.println(String.format("=======================%s=======================", StrUtil.isBlank(songlistName) ? singerName : songlistName));
List<Map<String, Object>> musics = new ArrayList<>();
result.put("title", StrUtil.isBlank(songlistName) ? singerName : songlistName);
for (JXNode song : songs) {
Element element = song.asElement();
String songName = element.text();
String songId = element.attr("href").split("=")[1];
String songUrl = OUT_LINK + songId;
Map<String, Object> map = new HashMap<>();
map.put("songId", songId);
map.put("songName", songName);
map.put("songUrl", songUrl);
map.put("title", StrUtil.isBlank(songlistName) ? singerName : songlistName);
//map.put("lyric", getMusicLyric(songId));
musics.add(map);
//单线程下载歌曲
//downloadSong(songName, songUrl, result.get("title").toString());
}
musics.forEach(x -> System.out.println(x)); //多线程下载歌曲
//multiDownload(musics);
result.put("songs", musics);
//System.out.println(result);
return result;
} /**
* 获取歌词
*
* @param songId
* @return
*/
public String getMusicLyric(String songId) {
String url = String.format("http://music.163.com/api/song/lyric?id=%s&lv=-1&kv=-1&tv=-1", songId);
Map<String, Object> header = new HashMap<>();
header.put("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36");
header.put("Referer", "https://music.163.com/");
header.put("Host", "music.163.com");
String res = HttpUtil.get(url, header);
return JSONObject.parseObject(res).getJSONObject("lrc").getString("lyric");
} /**
* 歌曲下载
*
* @param songName
* @param songUrl
* @param title
*/
public void downloadSong(String songName, String songUrl, String title) {
HttpUtil.downloadFile(songUrl,
FileUtil.file(DOWNLOAD_PATH + title + "\\", songName + ".mp3"));
Console.log("下载完成!" + "==》" + songName);
} /**
* 多线程下载
*
* @param list
*/
public void multiDownload(List<Map<String, Object>> list){
//使用多线程优化查询速度
int threadNum = 10;
if (list.size() < 10) {
threadNum = 1;
}
ExecutorService executorService = Executors.newFixedThreadPool(threadNum);
CountDownLatch countDownLatch = new CountDownLatch(threadNum); int perSize = list.size() / threadNum;
for (int i = 0; i < threadNum; i++) {
int start = i * perSize;
int end = (i + 1) * perSize;
if (i == threadNum - 1) {
end = list.size();
}
List<Map<String, Object>> maps = list.subList(start, end);
MultiThread thread = new MultiThread();
thread.setProjectList(maps);
thread.setCountDownLatch(countDownLatch);
executorService.submit(thread);
}
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
executorService.shutdown();
} class MultiThread extends Thread {
private List<Map<String, Object>> projectList; private CountDownLatch countDownLatch; private List<Map<String, Object>> result; public void setResultList(List<Map<String, Object>> result) {
this.result = result;
} public void setProjectList(List<Map<String, Object>> projectList) {
this.projectList = projectList;
} public void setCountDownLatch(CountDownLatch countDownLatch) {
this.countDownLatch = countDownLatch;
} @Override
public void run() {
try { for (Map<String, Object> map : projectList) {
downloadSong((String)map.get("songName"),(String)map.get("songUrl"),(String)map.get("title"));
} } catch (Exception e) {
e.printStackTrace();
} finally {
if (countDownLatch != null) {
countDownLatch.countDown();
}
}
}
}
}

使用Java Xpath 爬取某易云歌曲的更多相关文章

  1. 如何用Python网络爬虫爬取网易云音乐歌曲

    今天小编带大家一起来利用Python爬取网易云音乐,分分钟将网站上的音乐down到本地. 跟着小编运行过代码的筒子们将网易云歌词抓取下来已经不再话下了,在抓取歌词的时候在函数中传入了歌手ID和歌曲名两 ...

  2. 使用Xpath爬取酷狗TOP500的歌曲信息

    使用xpath爬取酷狗TOP500的歌曲信息, 将排名.歌手名.歌曲名.歌曲时长,提取的结果以文件形式保存下来.参考网址:http://www.kugou.com/yy/rank/home/1-888 ...

  3. Python爬取网易云音乐歌手歌曲和歌单

    仅供学习参考 Python爬取网易云音乐网易云音乐歌手歌曲和歌单,并下载到本地 很多人学习python,不知道从何学起.很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手.很多已经做 ...

  4. python网络爬虫&&爬取网易云音乐

    #爬取网易云音乐 url="https://music.163.com/discover/toplist" #歌单连接地址 url2 = 'http://music.163.com ...

  5. Python爬取网易云歌单

    目录 1. 关键点 2. 效果图 3. 源代码 1. 关键点 使用单线程爬取,未登录,爬取网易云歌单主要有三个关键点: url为https://music.163.com/discover/playl ...

  6. 用Python爬取网易云音乐热评

    用Python爬取网易云音乐热评 本文旨在记录Python爬虫实例:网易云热评下载 由于是从零开始,本文内容借鉴于各种网络资源,如有侵权请告知作者. 要看懂本文,需要具备一点点网络相关知识.不过没有关 ...

  7. python爬虫:了解JS加密爬取网易云音乐

    python爬虫:了解JS加密爬取网易云音乐 前言 大家好,我是"持之以恒_liu",之所以起这个名字,就是希望我自己无论做什么事,只要一开始选择了,那么就要坚持到底,不管结果如何 ...

  8. java爬虫爬取的html内容中空格(&nbsp;)变为问号“?”的解决方法

    用java编写的爬虫,使用xpath爬取内容后,发现网页源码中的 全部显示为?(问号),但是使用字符串的replace("?", ""),并不能替换,网上找了一 ...

  9. python爬虫+词云图,爬取网易云音乐评论

    又到了清明时节,用python爬取了网易云音乐<清明雨上>的评论,统计词频和绘制词云图,记录过程中遇到一些问题 爬取网易云音乐的评论 一开始是按照常规思路,分析网页ajax的传参情况.看到 ...

  10. 爬虫实战(二) 用Python爬取网易云歌单

    最近,博主喜欢上了听歌,但是又苦于找不到好音乐,于是就打算到网易云的歌单中逛逛 本着 "用技术改变生活" 的想法,于是便想着写一个爬虫爬取网易云的歌单,并按播放量自动进行排序 这篇 ...

随机推荐

  1. 三款Github Copilot的免费替代

    大家好我是费老师,提起Github Copilot,相信很多读者朋友们都听说过甚至使用过,作为Github研发的一款先进的编程辅助插件,它可以在我们日常编写代码的过程中,根据代码的上下文内容.注释等信 ...

  2. JavaScript原型与原型链深入理解

    原型: 每一个js 对象(null除外)都会和另一个对象相关联,"另一个"对象就被我们称之为'原型', 而每一个原型拥有一个prototype 属性指向原型对象(就是原型的实例)的 ...

  3. Python潮流周刊#5:并发一百万个任务要用多少内存?

    你好,我是猫哥.这里记录每周值得分享的 Python 及通用技术内容,部分为英文,已在小标题注明.(标题取自其中一则分享,不代表全部内容都是该主题,特此声明.) 博客原文:https://python ...

  4. 7. RESTful

    1. RESTful简介 ‍ REST:Representational State Transfer,表现层资源状态转移. ①资源 ‍ 资源是一种看待服务器的方式,即,将服务器看作是由很多离散的资源 ...

  5. vivo 自研鲁班分布式 ID 服务实践

    作者:vivo IT 平台团队- An Peng 本文介绍了什么是分布式ID,分布式ID的业务场景以及9种分布式ID的实现方式,同时基于vivo内部IT的业务场景,介绍了自研鲁班分布式ID服务的实践. ...

  6. 图像分割_评价指标_PSNR峰值信噪比和SSIM结构相似度

    PSNR psnr是"Peak Signal to Noise Ratio"的缩写,即峰值信噪比,是一种评价图像的客观标准. 为了衡量经过处理后的影像品质,我们通常会参考PSNR值 ...

  7. Windows商店开发者注册失败

    前言 最近写了个小工具想上架Windows应用商店,但是在填写信息那一页总是失败,提示Error code 2201. Correlation ID 9d436e3a-94df-498a-b224-8 ...

  8. asp.net core之配置

    简介 配置在asp.net core中可以说是我们必不可少一部分.ASP.NET Core 中的应用程序配置是使用一个或多个配置提供程序执行的. 配置提供程序使用各种配置源从键值对读取配置数据,普通最 ...

  9. Python和PyTorch深入实现线性回归模型:一篇文章全面掌握基础机器学习技术

    1. 简介 1.1 线性回归模型概述 线性回归是一种统计学中的预测分析,该方法用于建立两种或两种以上变量间的关系模型.线性回归使用最佳的拟合直线(也称为回归线)在独立(输入)变量和因变量(输出)之间建 ...

  10. 关于NOI2010“超级钢琴”的反思

    [NOI2010] 超级钢琴 题目描述 小 Z 是一个小有名气的钢琴家,最近 C 博士送给了小 Z 一架超级钢琴,小 Z 希望能够用这架钢琴创作出世界上最美妙的音乐. 这架超级钢琴可以弹奏出 \(n\ ...