网易云音乐开放api接口
网址:https://binaryify.github.io/NeteaseCloudMusicApi/#/?id=neteasecloudmusicapi
项目地址:https://github.com/Binaryify/NeteaseCloudMusicApi
下载下来之后,安装依赖:npm install
启动服务: node app.js
启动成功之后,根据api接口文档就可以获取请求的url了。
本文需求是,获取推荐歌单30张,并把数据存储到MySQL数据库,并且根据每张歌单的图片url将图片下载下来存到本地。
先看一下获取歌单列表的api文档
文档地址:https://binaryify.github.io/NeteaseCloudMusicApi/#/?id=neteasecloudmusicapi
全局搜索Ctrl + F 推荐歌单,可以看到一个api
试一试看能不能得到数据
把项目启动,网址输入:50张歌单
http://localhost:3000/personalized” />可以得到数据,现在来存储到数据库,并且下载图片
先看一下数据结构,存储哪些数据
这里我们只要歌单的id,picUrl,name,playCount先建表
springboot连接数据库,代码生成controller,service,mapper等,使用mybatis-plus
先存储
controller:
/** * 获取歌单列表 * api接口地址:https://binaryify.github.io/NeteaseCloudMusicApi/#/" />@GetMapping("/getListSongs")public ResponseWrapper getListSongs(){return gedanService.getListSongs();}
service实现
/** * 获取歌单列表 * api接口地址:https://binaryify.github.io/NeteaseCloudMusicApi/#/?id=neteasecloudmusicapi * 项目地址:https://github.com/Binaryify/NeteaseCloudMusicApi * 下载下来之后 * npm install * 运行 node app.js * 默认运行端口:3000 */@Overridepublic ResponseWrapper getListSongs() {// 推荐歌单的请求地址:http://localhost:3000/personalized?limit=/** * 推荐歌单 * 说明 : 调用此接口 , 可获取推荐歌单 * * 可选参数 : limit: 取出数量 , 默认为 30 (不支持 offset) * * 接口地址 : /personalized * * 调用例子 : /personalized?limit=1 */// 获取100个歌单String url = "http://localhost:3000/personalized?limit=50";String s = HttpUtils.sendGetRequest(url);log.info(s);// JSON字符串转JSONObject对象JSONObject jsonObj = JSONObject.parseObject(s);// JSONObject对象转mapMap<String, Object> map = JSONUtilsTool.JSONObjectToMap(jsonObj);log.info(map.toString());log.info(map.get("code").toString());if (map.get("code").toString().equals("200")){// 200 说明获取数据成功Object result = map.get("result");log.info(result.toString());// 获取到了歌单列表JSONArray resuArr = JSONObject.parseArray(result.toString());log.info(resuArr.get(0).toString());// JSONArray 转 listList<Gedan> gedanList = resuArr.toJavaList(Gedan.class);log.info(gedanList.size() + "张歌单");// 把歌单信息存入数据库for (Gedan gedan : gedanList) {List<Gedan> gedans = gedanMapper.selectList(new LambdaQueryWrapper<Gedan>().eq(Gedan::getId, gedan.getId()));if (gedans.size() > 0){for (Gedan gedan1 : gedans) {gedan1.setName(gedan.getName());gedan1.setPicUrl(gedan.getPicUrl());gedan1.setPlayCount(gedan.getPlayCount());gedanMapper.updateById(gedan1);}}else {gedanMapper.insert(gedan);}}log.info("歌单数据保存数据库成功");return ResponseWrapper.markCustomSuccess("数据保存数据库成功");}else {log.info("数据获取失败");return ResponseWrapper.markCustomError("数据请求失败");}}
HttpUtils.sendGetRequest方法:
/** * 发送get请求,没有参数 * * @param url * @return */public static String sendGetRequest(String url) {String result = "";BufferedReader in = null;try {URL realUrl = new URL(url);// 打开和URL之间的连接HttpURLConnection connection = (HttpURLConnection) realUrl.openConnection();// 设置通用的请求属性connection.setRequestProperty("accept", "*/*");connection.setRequestProperty("connection", "Keep-Alive");connection.setRequestProperty("user-agent","Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");// 建立实际的连接connection.connect();// 定义 BufferedReader输入流来读取URL的响应 (防止中文乱码可以换成“gbk”)in = new BufferedReader(new InputStreamReader(connection.getInputStream(), "utf-8"));String line;while ((line = in.readLine()) != null) {result += line;}} catch (Exception e) {System.out.println("发送GET请求出现异常!" + e);e.printStackTrace();}// 使用finally块来关闭输入流finally {try {if (in != null) {in.close();}} catch (Exception e) {e.printStackTrace();}}return result;}
JSONUtilsTool.JSONObjectToMap方法:
/** * JSONObject转map * @param jsonObject * @return map对象 */public static Map<String,Object> JSONObjectToMap(JSONObject jsonObject){if (jsonObject.isEmpty()){return new HashMap<String,Object>();}else {HashMap<String, Object> map = new HashMap<>();for (Map.Entry<String, Object> entry : jsonObject.entrySet()) {map.put(entry.getKey(), entry.getValue());}log("map对象:" + map);if (map.size() > 0){return map;}else {return new HashMap<>();}}}
歌单实体类:
import com.baomidou.mybatisplus.annotation.IdType;import com.baomidou.mybatisplus.annotation.TableId;import lombok.Data;import lombok.EqualsAndHashCode;import java.io.Serializable;/** *
* 网易云音乐歌单 *
* * @author fzg * @since 2022-12-05 */@Data@EqualsAndHashCode(callSuper = false)public class Gedan implements Serializable {private static final long serialVersionUID = 1L;@TableId(value = "aid", type = IdType.AUTO)private Integer aid;/** * 歌单图片url */private String picUrl;/** * 歌单点击量 */private Long playCount;/** * 歌单名字 */private String name;/** * 歌单id */private Long id;}最后启动项目输入controller的get请求
数据已成功存入数据库
接下来下载图片到本地
controller:
/** * 数据库查询歌单的图片url *根据url下载图片到本地 */@GetMapping("/downLoadGeDanPicByDataBaseQuery")public ResponseWrapper downLoadGeDanPicByDataBaseQuery(){return gedanService.downLoadGeDanPicByDataBaseQuery();}
Service实现类:
/** * 数据库查询歌单的图片url * 根据url下载图片到本地 */@Overridepublic ResponseWrapper downLoadGeDanPicByDataBaseQuery() {ArrayList<String> res = new ArrayList<>();List<Gedan> gedanList = gedanMapper.selectList(null);if (gedanList.size() > 0){String path = "E:\\pictures\\wangyiyun-imgs\\gedan";for (Gedan gedan : gedanList) {String name = "歌单图片" + gedan.getId();String url = gedan.getPicUrl();File file = new File(path + "\\" + name + ".jpg");if (file.exists()){res.add(name + ".jpg 已存在");}else {try {ImageCodeTool.download(url,name,path);res.add(name + "下载成功");} catch (Exception e) {res.add(name + "下载失败");e.printStackTrace();}}}return ResponseWrapper.markCustomSuccess("歌单图片下载完成,本地路径:" + path,res);}else {return ResponseWrapper.markCustomError("数据库查询歌单为空");}}
ImageCodeTool.download方法:
/** * java 通过url下载图片保存到本地 * @param urlString 图片链接地址 * @param imgName 图片名称 * @param path 图片要保存的路径 * @throws Exception */public static void download(String urlString, String imgName, String path) throws Exception {// 构造URLURL url = new URL(urlString);// 打开连接URLConnection con = url.openConnection();// 输入流InputStream is = con.getInputStream();// 1K的数据缓冲byte[] bs = new byte[1024];// 读取到的数据长度int len;// 输出的文件流String filename = path + "\\" + imgName + ".jpg";//本地路径及图片名称File file = new File(filename);FileOutputStream os = new FileOutputStream(file, true);// 开始读取while ((len = is.read(bs)) != -1) {os.write(bs, 0, len);}// System.out.println(imgName);// 完毕,关闭所有链接os.close();is.close();}
最后启动服务,输入controller中get请求的网址
图片已经下载成功