Java爬取并下载酷狗音乐

本文方法及代码仅供学习,仅供学习。

案例:

  下载酷狗TOP500歌曲,代码用到的代码库包含:Jsoup、HttpClient、fastJson等。

正文:

  1、分析是否可以获取到TOP500歌单

打开酷狗首页,查看TOP500,发现存在分页,每页显示22条歌曲,

发现酷狗的链接如下:

https://www.kugou.com/yy/rank/home/1-8888.html?from=homepage

通过更改链接中的1可以进行分页,所以我们可以通过更改链接地址获取其余的歌曲。

2、分析找到正真的mp3下载地址

 点一个歌曲进入播放页面,使用谷歌浏览器的控制台的Elements,搜一下mp3,很轻松就定位到了MP3的位置。

但是使用java访问的时候爬取的html里却没有该mp3的文件地址,那么这肯定是在该页面的位置使用了js来加载mp3,那么刷新下网页,看网页加载了哪些东西,加载的东西有点多,着重看一下js、php的请求,主要是看里面有没有mp3的地址。

最终在列表中找到:

https://wwwapi.kugou.com/yy/index.php?r=play/getdata&callback=jQuery191044492686523157987_1559446927765&hash=458E9B9F362277AC37E9EEF1CB80B535&album_id=18712576&dfid=1ZxQbe0MiP8J09j5tR0Np9IA&mid=9393340fecff864a4d6c4e95099b2be1&platid=4&_=1559446927766

这个请求结果中发现了mp3的完整地址:

那这个js是怎么判断是哪首歌的呢,那么只可能是hash这个参数来决定歌曲的,然后到播放页面里找到这个hash的位置,是在下面的js里:

var dataFromSmarty = [{"hash":"667939C6E784265D541DEEE65AE4F2F8","timelength":"237051","audio_name":"\u767d\u5c0f\u767d - \u6700\u7f8e\u5a5a\u793c","author_name":"\u767d\u5c0f\u767d","song_name":"\u6700\u7f8e\u5a5a\u793c","album_id":0}],//当前页面歌曲信息playType = "search_single";//当前播放</script>

在去java爬取该网页,查看能否爬到这个hash,果然,爬取的html里有这段js,到现在mp3的地址也找到了,歌单也找到了,那么下一步就用程序实现就可以了。

3、代码实现

SpiderKugou.java
package com.billy.test;import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;/*** 爬取并下载酷狗的歌曲*/
public class SpiderKugou {private static String filePath;//酷狗地址private static String LINK;//mp3地址private static String mp3;static {filePath = "F:/music/";LINK = "https://www.kugou.com/yy/rank/home/PAGE-8888.html?from=rank";mp3 = "https://wwwapi.kugou.com/yy/index.php?r=play/getdata&callback=jQuery19103632090130122796_1558800325111&"+ "hash=HASH&_=TIME";}public static void main(String[] args) throws Exception {for(int i = 5 ; i < 23 ; i++){String url = LINK.replace("PAGE", i + "");downSong(url);}}/*** 下载歌曲* @param url* @throws Exception*/private static void downSong(String url) throws Exception{HttpGetConnect connect = new HttpGetConnect();String content = connect.connect(url, "utf-8");HtmlManage html = new HtmlManage();Document doc = html.manage(content);Element ele = doc.getElementsByClass("pc_temp_songlist").get(0);Elements elements = ele.getElementsByTag("li");for(int i = 0 ; i < elements.size() ; i++){Element item = elements.get(i);String title = item.attr("title").trim();String link = item.getElementsByTag("a").first().attr("href");downLoad(link,title);Thread.sleep(1000);}}/*** 下载* @param url* @param name* @throws IOException*/private static void downLoad(String url,String name) throws IOException{String hash = "";HttpGetConnect connect = new HttpGetConnect();String content = connect.connect(url, "utf-8");String regEx = "\"hash\":\"[0-9A-Z]+\"";// 编译正则表达式Pattern pattern = Pattern.compile(regEx);Matcher matcher = pattern.matcher(content);if (matcher.find()) {hash = matcher.group();hash = hash.replace("\"hash\":\"", "");hash = hash.replace("\"", "");}String item = mp3.replace("HASH", hash);item = item.replace("TIME", System.currentTimeMillis() + "");System.out.println("item:" + item);String mp = connect.connect(item, "utf-8");mp = mp.substring(mp.indexOf("(") + 1, mp.length() - 3);JSONObject json = JSON.parseObject(mp);if(Integer.parseInt(json.get("status") + "") != 0){String playUrl = json.getJSONObject("data").getString("play_url");FileDownload down = new FileDownload();down.download(playUrl, filePath + name + ".mp3");}}}
View Code
HttpGetConnect.java
package com.billy.test;import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.BasicHttpClientConnectionManager;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;/*** httpclient 工具类*/
public class HttpGetConnect {/***  获取html内容* @param url* @param charsetName  UTF-8、GB2312* @return* @throws IOException*/public static String connect(String url,String charsetName) throws IOException{BasicHttpClientConnectionManager connManager = new BasicHttpClientConnectionManager();CloseableHttpClient httpclient = HttpClients.custom().setConnectionManager(connManager).build();String content = "";try{HttpGet httpget = new HttpGet(url);RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(5000).setConnectTimeout(50000).setConnectionRequestTimeout(50000).build();httpget.setConfig(requestConfig);httpget.setHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");httpget.setHeader("Accept-Encoding", "gzip,deflate,sdch");httpget.setHeader("Accept-Language", "zh-CN,zh;q=0.8");httpget.setHeader("Connection", "keep-alive");httpget.setHeader("Upgrade-Insecure-Requests", "1");httpget.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36");httpget.setHeader("cache-control", "max-age=0");httpget.setHeader("Referer","https://www.kugou.com/song/");//设置cookiehttpget.setHeader("Cookie", "kg_mid=9393340fecff864a4d6c4e95099b2be1;");CloseableHttpResponse response = httpclient.execute(httpget);int status = response.getStatusLine().getStatusCode();if (status >= 200 && status < 300) {HttpEntity entity = response.getEntity();InputStream instream = entity.getContent();BufferedReader br = new BufferedReader(new InputStreamReader(instream,charsetName));StringBuffer sbf = new StringBuffer();String line = null;while ((line = br.readLine()) != null){sbf.append(line + "\n");}br.close();content = sbf.toString();} else {content = "";}}catch(Exception e){e.printStackTrace();}finally{httpclient.close();}log.info("content is " + content);return content;}private static Log log = LogFactory.getLog(HttpGetConnect.class);
}
View Code
HtmlManage.java
package com.billy.test;import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;import java.io.IOException;
import java.util.ArrayList;
import java.util.List;/*** html manage 工具类*/
public class HtmlManage {public Document manage(String html) {Document doc = Jsoup.parse(html);return doc;}public Document manageDirect(String url) throws IOException {Document doc = Jsoup.connect(url).get();return doc;}public List<String> manageHtmlTag(Document doc, String tag) {List<String> list = new ArrayList<String>();Elements elements = doc.getElementsByTag(tag);for (int i = 0; i < elements.size(); i++) {String str = elements.get(i).html();list.add(str);}return list;}public List<String> manageHtmlClass(Document doc, String clas) {List<String> list = new ArrayList<String>();Elements elements = doc.getElementsByClass(clas);for (int i = 0; i < elements.size(); i++) {String str = elements.get(i).html();list.add(str);}return list;}public List<String> manageHtmlKey(Document doc, String key, String value) {List<String> list = new ArrayList<String>();Elements elements = doc.getElementsByAttributeValue(key, value);for (int i = 0; i < elements.size(); i++) {String str = elements.get(i).html();list.add(str);}return list;}private static Log log = LogFactory.getLog(HtmlManage.class);
}
View Code
FileDownload.java
package com.billy.test;import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;/*** 文件下载工具类*/
public class FileDownload {/*** 文件下载** @param url  链接地址* @param path 要保存的路径及文件名* @return*/public static boolean download(String url, String path) {boolean flag = false;CloseableHttpClient httpclient = HttpClients.createDefault();RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(2000).setConnectTimeout(2000).build();HttpGet get = new HttpGet(url);get.setConfig(requestConfig);BufferedInputStream in = null;BufferedOutputStream out = null;try {for (int i = 0; i < 3; i++) {CloseableHttpResponse result = httpclient.execute(get);System.out.println(result.getStatusLine());if (result.getStatusLine().getStatusCode() == 200) {in = new BufferedInputStream(result.getEntity().getContent());File file = new File(path);out = new BufferedOutputStream(new FileOutputStream(file));byte[] buffer = new byte[1024];int len = -1;while ((len = in.read(buffer, 0, 1024)) > -1) {out.write(buffer, 0, len);}flag = true;break;} else if (result.getStatusLine().getStatusCode() == 500) {continue;}}} catch (Exception e) {e.printStackTrace();flag = false;} finally {get.releaseConnection();try {if (in != null) {in.close();}if (out != null) {out.close();}} catch (Exception e) {e.printStackTrace();flag = false;}}return flag;}private static Log log = LogFactory.getLog(FileDownload.class);
}
View Code

 

 
 
 
 

 

转载于:https://www.cnblogs.com/BillyYoung/p/10962441.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/248820.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Webpack/Vue-cli两种方式加载markdown文件并实现代码高亮

准备的资源&#xff1a; highlight.js &#xff1a; 实现代码高亮&#xff0c;通过npm install highlight.js -D安装 vue-markdown-loader&#xff1a;解析md文件的必备loader&#xff0c;通过npm install vue-markdown-loader -D安装 下面我们分两个场景来说明一下md文件的…

新浪微博第三方登陆重定向错误23123

新浪微博第三方登陆重定向错误23123 2019年06月02日 13:49:43 温室花朵 阅读数&#xff1a;2更多 个人分类&#xff1a; 第三方微博登陆21323编辑当我们使用微博第三方登陆的时候&#xff0c;发现登陆出错了&#xff0c;错误码为&#xff1a;21323&#xff0c;解决方案如下&…

Utility Manager 的一些百度不了的操作

一进来是不是这样的&#xff01; 那突然出了点问题&#xff0c;咋办呢&#xff01; 就像这样子的&#xff0c; 恢复默认布局就OK啦&#xff01;哈哈哈&#xff0c;太聪明啦&#xff0c;但是百度了好长时间还是找不到啊&#xff0c;怎么办呐&#xff0c;烦死啦&#xff01; 其实…

记录一次内网渗透试验

0x00 前言 目标&#xff1a;给了一个目标机ip&#xff0c;要求得到该服务器权限&#xff0c;并通过该ip渗透至内网控制内网的两台服务器 攻击机&#xff1a;kali (192.168.31.51) 目标机&#xff1a;windows 2003 (192.168.31.196) 0x01 信息收集 nmap端口探测 御剑后台扫描 …

2018-2019 1 20165203 实验五 通用协议设计

2018-2019 1 20165203 实验五 通用协议设计 OpenSSL学习 定义&#xff1a;OpenSSL是为网络通信提供安全及数据完整性的一种安全协议&#xff0c;囊括了主要的密码算法、常用的密钥和证书封装管理功能以及SSL协议&#xff0c;并提供了丰富的应用程序供测试或其它目的使用。基本功…

弄懂webpack,只要看这一片就够了(文末有福利)

什么是webpack ​ webpack是什么&#xff0c;官网中是这么说的。 ​ 本质上&#xff0c;webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时&#xff0c;它会递归地构建一个依赖关系图(dependency graph)&#xff0c;其中包…

beta冲刺总结那周余嘉熊掌将得队

作业格式 课程名称&#xff1a;软件工程1916|W&#xff08;福州大学&#xff09;作业要求&#xff1a;项目Beta冲刺团队名称&#xff1a; 那周余嘉熊掌将得队作业目标&#xff1a;beta冲刺总结队员学号队员姓名博客地址备注221600131Jaminhttps://www.cnblogs.com/JaminWu/队长…

在Winform中菜单动态添加“最近使用文件”

最近在做文件处理系统中&#xff0c;要把最近打开文件显示出来&#xff0c;方便用户使用。网上资料有说&#xff0c;去遍历“C:\Documents and Settings\Administrator\Recent”下的最近文档本。文主要介绍在Winform界面菜单中实现【最近使用的文件】动态菜单的处理&#xff0c…

Vue组件通信原理剖析(一)事件总线的基石 $on和$emit

首先我们先从一个面试题入手。 面试官问&#xff1a; “Vue中组件通信的常用方式有哪些&#xff1f;” 我答&#xff1a; 1. props 2. 自定义事件 3. eventbus 4. vuex 5. 还有常见的边界情况$parent、$children、$root、$refs、provide/inject 6. 此外还有一些非props特性$att…

display:flex弹性布局

一、背景 前段时间帮公司运维小姑娘调整她自己写的页面样式时发现她用了display: flex&#xff0c;我这个后端老古董还不太懂flex&#xff0c;自愧不如啊&#xff0c;所以写篇博客记录学习下。 现在写的前端页面还停留在依赖 display 属性 position属性 float属性的布局方式&…

Vue组件通信原理剖析(二)全局状态管理Vuex

首先我们先从一个面试题入手。 面试官问&#xff1a; “Vue中组件通信的常用方式有哪些&#xff1f;” 我答&#xff1a; 1. props 2. 自定义事件 3. eventbus 4. vuex 5. 还有常见的边界情况$parent、$children、$root、$refs、provide/inject 6. 此外还有一些非props特性$att…

初识单点登录及JWT实现

单点登录 多系统&#xff0c;单一位置登录&#xff0c;实现多系统同时登录的一种技术 &#xff08;三方登录&#xff1a;某系统使用其他系统的用户&#xff0c;实现本系统登录的方式。如微信登录、支付宝登录&#xff09; 单点登录一般是用于互相授信的系统&#xff0c;实现单一…

Vue组件通信原理剖析(三)provide/inject原理分析

首先我们先从一个面试题入手。 面试官问&#xff1a; “Vue中组件通信的常用方式有哪些&#xff1f;” 我答&#xff1a; 1. props 2. 自定义事件 3. eventbus 4. vuex 5. 还有常见的边界情况$parent、$children、$root、$refs、provide/inject 6. 此外还有一些非props特性$att…

iMX6开发板-uboot-网络设置和测试

本文章基于迅为IMX6开发板 将iMX6开发板通过网线连接到路由器&#xff0c;同时连接好调试串口&#xff0c;上电立即按 enter&#xff0c;即可进入 uboot。然后输入命令 pri&#xff0c;查看开发板当前的配置&#xff0c;如下图所示可以看到 ip 地址、子网掩码 等信息。 本文档测…

Django ajax 检测用户名是否已被注册

添加一个 register.html 页面 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title> </head> <body> <form><p>用户名<input id"username" type&…

详解JDBC连接数据库

一、概念 1. 为了能让程序操作数据库&#xff0c;对数据库中的表进行操作&#xff0c;每一种数据库都会提供一套连接和操作该数据库的驱动&#xff0c;而且每种数据库的驱动都各不相同&#xff0c;例如mysql数据库使用mysql驱动&#xff0c;oracle数据库使用oracle驱动&#xf…

ZOJ4024 Peak

题意 给出一个数组 判断这个数组是否形成了一个“山峰” 即中间有个数最大 从第一个数到这个数递增 从这个数到最后一个数递减 模拟 从两端分别以递增和递减判断 看第一个不满足递增或递减的数是否相等并且没越界就可以了 AC代码&#xff1a; 1 #include<bits/stdc.h>2 u…

springmvc跨域问题

1、跨域问题&#xff1a; 按照网上所有的方法试了一遍&#xff0c;都没跨过去&#xff0c;正在无助之际&#xff0c;使用filter按照下面的方法解决的时候出现了转机&#xff1a; 添加filter&#xff1a; package com.thc.bpm.filter;import javax.servlet.*; import javax.serv…

成功秀了一波scala spark ML逻辑斯蒂回归

1、直接上官方代码&#xff0c;调整过的&#xff0c;方可使用 package com.test import org.apache.spark.{SparkConf, SparkContext} import org.apache.spark.mllib.classification.{LogisticRegressionModel, LogisticRegressionWithLBFGS} import org.apache.spark.mllib.e…

nodeJS中的异步编程

nodejs 不是单线程 在博客项目中关于异步问题&#xff1a; 1.当用户添加一条博客时 需要通过post方式向服务器发送数据 后台获取用户以post方式拿到传送过来的数据 然后存入数据库&#xff1a; 上面的代码&#xff1a;创建一个空字符串 当用户向服务器发送请求时出发data事件将…