使用Java Xpath 爬取某易云歌曲
本文使用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 爬取某易云歌曲的更多相关文章
- 如何用Python网络爬虫爬取网易云音乐歌曲
今天小编带大家一起来利用Python爬取网易云音乐,分分钟将网站上的音乐down到本地. 跟着小编运行过代码的筒子们将网易云歌词抓取下来已经不再话下了,在抓取歌词的时候在函数中传入了歌手ID和歌曲名两 ...
- 使用Xpath爬取酷狗TOP500的歌曲信息
使用xpath爬取酷狗TOP500的歌曲信息, 将排名.歌手名.歌曲名.歌曲时长,提取的结果以文件形式保存下来.参考网址:http://www.kugou.com/yy/rank/home/1-888 ...
- Python爬取网易云音乐歌手歌曲和歌单
仅供学习参考 Python爬取网易云音乐网易云音乐歌手歌曲和歌单,并下载到本地 很多人学习python,不知道从何学起.很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手.很多已经做 ...
- python网络爬虫&&爬取网易云音乐
#爬取网易云音乐 url="https://music.163.com/discover/toplist" #歌单连接地址 url2 = 'http://music.163.com ...
- Python爬取网易云歌单
目录 1. 关键点 2. 效果图 3. 源代码 1. 关键点 使用单线程爬取,未登录,爬取网易云歌单主要有三个关键点: url为https://music.163.com/discover/playl ...
- 用Python爬取网易云音乐热评
用Python爬取网易云音乐热评 本文旨在记录Python爬虫实例:网易云热评下载 由于是从零开始,本文内容借鉴于各种网络资源,如有侵权请告知作者. 要看懂本文,需要具备一点点网络相关知识.不过没有关 ...
- python爬虫:了解JS加密爬取网易云音乐
python爬虫:了解JS加密爬取网易云音乐 前言 大家好,我是"持之以恒_liu",之所以起这个名字,就是希望我自己无论做什么事,只要一开始选择了,那么就要坚持到底,不管结果如何 ...
- java爬虫爬取的html内容中空格( )变为问号“?”的解决方法
用java编写的爬虫,使用xpath爬取内容后,发现网页源码中的 全部显示为?(问号),但是使用字符串的replace("?", ""),并不能替换,网上找了一 ...
- python爬虫+词云图,爬取网易云音乐评论
又到了清明时节,用python爬取了网易云音乐<清明雨上>的评论,统计词频和绘制词云图,记录过程中遇到一些问题 爬取网易云音乐的评论 一开始是按照常规思路,分析网页ajax的传参情况.看到 ...
- 爬虫实战(二) 用Python爬取网易云歌单
最近,博主喜欢上了听歌,但是又苦于找不到好音乐,于是就打算到网易云的歌单中逛逛 本着 "用技术改变生活" 的想法,于是便想着写一个爬虫爬取网易云的歌单,并按播放量自动进行排序 这篇 ...
随机推荐
- 【汇编】老师太hun
老师只是随手发实验项目卡,从未提过实验报告的事情 可是 他却要在 复习周 一下子 收6次 实验报告 也不发资料,不说每次的时间点,不讲实验 这人心中有 学生 吗? 上课发 上个班直播的录播 一节课就发 ...
- 啊哈C语言案例学习笔记
Hello World #include<stdio.h> /* 技术要点: 初学者在编写程序时,经常会忘记在语句后边添加分号, */ int main() { printf(" ...
- 2014年蓝桥杯C/C++大学B组省赛真题(奇怪的分式)
题目描述: 上小学的时候,小明经常自己发明新算法.一次,老师出的题目是:1/4 乘以 8/5 小明居然把分子拼接在一起,分母拼接在一起,答案是:18/45 (参见图1.png)老师刚想批评他,转念一想 ...
- 2013年蓝桥杯C/C++大学B组省赛真题(翻硬币)
题目描述: 明正在玩一个"翻硬币"的游戏. 桌上放着排成一排的若干硬币.我们用 * 表示正面,用 o 表示反面(是小写字母,不是零). 比如,可能情形是:**oo***oooo 如 ...
- 1.1. Java简介与安装
Java简介 Java是一种广泛使用的计算机编程语言,由James Gosling和他的团队在Sun Microsystems公司开发,于1995年首次发布.Java的设计理念是"一次编写, ...
- drf之频率类源码
1 频率类 写一个类,继承SimpleRateThrottle,重写get_cache_key,返回[ip,用户id]什么,就以什么做限制,编写类属性 scope = 字符串,在配置文件中配置 'DE ...
- Galaxy Project 是一个开源的生物医学分析平台项目。在 Github 的 #8475 上有个讨论,可以动态开启 message_box_content, admin_users, w......
本文分享自微信公众号 - 生信科技爱好者(bioitee).如有侵权,请联系 support@oschina.cn 删除.本文参与"OSC源创计划",欢迎正在阅读的你也加入,一起分 ...
- 白帽子讲web安全
世界安全观 Web安全筒史 起初,研究计算机系统和网络的人,被称为"Hacker","Hacker"在中国按照音译,被称为"黑客" 对于现代 ...
- 前端Vue自定义服务说明弹窗弹框 自下而上底部弹框
前端Vue自定义服务说明弹窗弹框 自下而上底部弹框, 请访问uni-app插件市场地址:https://ext.dcloud.net.cn/plugin?id=13108 效果图如下: cc-serv ...
- 人工智能智能城市(AIinSmartCities)领域的100篇热门博客文章标题如下:
目录 人工智能智能城市(AI in Smart Cities)领域的100篇热门博客文章标题如下: 1.<智能城市与大数据:未来城市大脑的发展方向> 2.<智能交通系统的设计与实现& ...