本文使用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. url函数

    url() 函数看起来的格式象:url(r^/account/$', views.index, name=index),它可以接收四个参数,分别是两个必选参数:regex.view 和两个可选参数:k ...

  2. VuePress v2.0 项目创建

    VuePress v2.0 项目创建 参考:VuePress v2.0 文档 1.创建文件夹 我创建了一个文件夹,然后在文件夹中打开了powershell E:\2023个人项目\terramours ...

  3. 一文吃透Java并发高频面试题

    内容摘自我的学习网站:topjavaer.cn 分享50道Java并发高频面试题. 线程池 线程池:一个管理线程的池子. 为什么平时都是使用线程池创建线程,直接new一个线程不好吗? 嗯,手动创建线程 ...

  4. 如何从零开始构建 API ?

    假设你请承包商从零开始建造一座房子,你肯定期望他们交付最高质量的房子.他们必须通过检查.遵守安全规范并遵循项目中约定的要求.因为建房子可容不得走捷径.如果承包商经常走捷径,他们的声誉会受到影响,从而失 ...

  5. Nginx SSL 双向认证

    安装Nginx和OpenSSL yum install nginx openssl -y SSL 服务器 / 客户端双向验证证书的生成 创建一个新的 CA 根证书,在 nginx 安装目录下新建 ca ...

  6. 从零实现俄罗斯方块(c语言+思路分析)

    俄罗斯方块 文章说明: 本文大部分参考至俄罗斯方块(C语言实现)_c语言俄罗斯方块_2021dragon的博客-CSDN博客,本人经过修改编辑,改变了文章的一些思路顺序,使得新手便于理解(个人想法). ...

  7. Rust 过程宏 proc-macro 是个啥

    定义一个 procedural macro 新建一个 lib 类型的 crate: cargo new hello-macro --lib procedural macros 只能在 proc-mac ...

  8. 4.4 x64dbg 绕过反调试保护机制

    在Windows平台下,应用程序为了保护自己不被调试器调试会通过各种方法限制进程调试自身,通常此类反调试技术会限制我们对其进行软件逆向与漏洞分析,下面是一些常见的反调试保护方法: IsDebugger ...

  9. NoSuchMethodError: Closure call with mismatched arguments:

    原因:某个方法的参数中,回调函数写的有问题,

  10. JavaScript中this的绑定

    <svg xmlns="http://www.w3.org/2000/svg" style="display: none;"> <path s ...