根据获得歌手的json数据的url

https://u.y.qq.com/cgi-bin/musicu.fcg?format=jsonp&inCharset=utf8&outCharset=utf-8&data=%7B%22comm%22%3A%7B%22ct%22%3A24%2C%22cv%22%3A10000%7D%2C%22singerList%22%3A%7B%22module%22%3A%22Music.SingerListServer%22%2C%22method%22%3A%22get_singer_list%22%2C%22param%22%3A%7B%22area%22%3A-100%2C%22sex%22%3A-100%2C%22genre%22%3A-100%2C%22index%22%3A1%2C%22sin%22%3A0%2C%22cur_page%22%3A1%7D%7D%7D

json数据部分截图

根据上面链接里获得数据,取出歌手mid,然后再根据下面的url获得歌曲列表

https://c.y.qq.com/v8/fcg-bin/fcg_v8_singer_track_cp.fcg?inCharset=utf8&outCharset=utf-8&notice=0&platform=yqq&needNewCode=0&singermid=002J4UUk29y8BY&order=listen&begin=0&num=30

json数据部分截图

下面是调用的详细代码,其中的HTTPUtil.sendGet方法是发送http请求的代码。在我这个博客

https://blog.csdn.net/Hello_Ray/article/details/80762232 里的代码11行代码和42-48行有http发送请求的代码,可以参考那个。

在测试这个方法,dao方法可以注释掉, HotSongSpider是引入别的类中转换list的方法,可以注释掉。

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jsoup.Jsoup;
import org.springframework.stereotype.Component;import javax.annotation.Resource;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.*;/*** <p>description: </p>** @author chenrui* @since 2018-08-09*/
@Component
public class SpiderSingerNew {private static Logger log = LogManager.getLogger(SpiderSingerNew.class);@Resourceprivate HotSongSpider hotSongSpider;@Resourceprivate HotSongDao hotSongDao;private Integer singerListTotalPage = 1;  //所有页数private Integer singerSongListTotalPage = 1;//成功的歌手列表List<QQ2Singer> singerList = new ArrayList<>();//爬取歌手列表出现的错误标签和页面public static Queue<Map<String, Integer>> errorSingerList = new LinkedList<>();public static Queue<Map<String, String>> errorSingerSongList = new LinkedList<>();//爬取所有歌手的urlString singerListUrl = "https://u.y.qq.com/cgi-bin/musicu.fcg?format=jsonp&inCharset=utf8&outCharset=utf-8&data=";String param = "{\"comm\":{\"ct\":24,\"cv\":10000},\"singerList\":{\"module\":\"Music.SingerListServer\",\"method\":\"get_singer_list\",\"param\":{\"area\":-100,\"sex\":-100,\"genre\":-100,\"index\":{index},\"sin\":{sin},\"cur_page\":{cur_page}}}}";//歌手下的全部歌曲String singerSongListUrl = "https://c.y.qq.com/v8/fcg-bin/fcg_v8_singer_track_cp.fcg?inCharset=utf8&outCharset=utf-8&notice=0&platform=yqq&needNewCode=0&singermid={singermid}&order=listen&begin={begin}&num={num}";public void spiderSingerList() {log.info("--start spider singer list--");int index = 1;//singer的listList<QQ2Singer> qq2SingerList = new ArrayList<>();try {for(; index<=27; index++) {for(int i=0; i < singerListTotalPage; i++) {String sendParam = param.replace("{index}", String.valueOf(index)).replace("{sin}", String.valueOf(i*80)).replace("{cur_page}", String.valueOf(i+1));String sendUrl = singerListUrl + URLEncoder.encode(sendParam, String.valueOf(StandardCharsets.UTF_8));String content = HTTPUtil.sendGet(sendUrl).getContent();parseSingerList(content, index, i);}//TODO 计算总页数singerListTotalPage=1;}} catch (Exception e) {log.error("error : start spider singer list {} {}", e.getMessage(), e.getCause());e.printStackTrace();}//循环处理出错的歌手,最多四次if(errorSingerList.size() > 0) {int singerEndlessFlag = 1;do {spiderErrorSingerList();singerEndlessFlag++;} while(singerEndlessFlag < 4 && errorSingerList.size()>0);}log.info("--finish spider singer list--");log.info("--start spider singer song list--");for(int i=0; i<singerList.size();i++) {String singermid = singerList.get(i).getSinger_mid();System.out.println("--开始第"+ (i+1) +"/"+singerList.size()+" singermid: "+ singermid +" 歌手的歌曲爬取--");spiderSingerSongList(singermid);}log.info("--处理歌手歌曲下的错误--");if(errorSingerSongList.size() > 0) {//循环处理出错的歌手,最多四次int songEndlessFlag = 1;do {spiderErrorSingerSongList();songEndlessFlag++;} while(errorSingerSongList.size()>0 && songEndlessFlag < 4  );}log.info("--finish spider singer song list--");}private int sum = 0;/*** singerlist是全局变量* 爬取全网的歌手速度很快,不用受到限制,所以先将歌手爬完再去爬取歌曲。* @param content* @param index* @param page*/public void parseSingerList(String content, int index, int page) {log.info("开始 index:{} page:{} 将singer的json数组转为singer的list集合", index, page+1);JSONObject json = JSONObject.parseObject(content);try {//TODO 计算总页数if(singerListTotalPage<=1) {int total = json.getJSONObject("singerList").getJSONObject("data").getInteger("total");sum += total;System.out.println("singer list的index: "+index+" page: "+ page +" " + total + " sum " + sum);singerListTotalPage = (total + 80 - 1) / 80;}//将singer的json数组转为singer的list集合JSONArray singerListJsonArray = json.getJSONObject("singerList").getJSONObject("data").getJSONArray("singerlist");for(int i=0; i<singerListJsonArray.size(); i++) {QQ2Singer qq2Singer = singerListJsonArray.getJSONObject(i).toJavaObject(QQ2Singer.class);//将歌手信息添加到全局变量中singerList.add(qq2Singer);/*hotSongDao.saveQQSinger(qq2Singer);*/hotSongDao.update(qq2Singer);}} catch (Exception e) {log.error("转换singerlist,url标签位置{}, 所在页面{}, 出现错误 {} {}", index, page,e.getMessage(), e.getCause());Map<String , Integer> errorInfo = new HashMap<>();errorInfo.put("index", index);errorInfo.put("page", page);errorSingerList.add(errorInfo);}log.info("完成 index:{} page:{} 将singer的json数组转为singer的list集合", index, page+1);}/*** 继续根据歌手列表出现的错误标签和页面爬取歌手* errorSingerList定义的全局变量*/public void spiderErrorSingerList() {Map<String, Integer> errorMap = errorSingerList.poll();while(errorMap!= null) {int index = errorMap.get("index");int page = errorMap.get("page");try {String sendParam = param.replace("{index}", String.valueOf(index)).replace("{sin}", String.valueOf(page*80)).replace("{cur_page}", String.valueOf(page+1));String sendUrl = singerListUrl + URLEncoder.encode(sendParam, String.valueOf(StandardCharsets.UTF_8));String content = HTTPUtil.sendGet(sendUrl).getContent();//根据index和page爬取对应的歌手parseSingerList(content, index, page);errorMap = errorSingerList.poll();} catch (Exception e) {Map<String , Integer> errorInfo = new HashMap<>();errorInfo.put("index", index);errorInfo.put("page", page);errorSingerList.add(errorInfo);}}}/*** 爬取歌手下的全部歌曲* @param singerMid*/public void spiderSingerSongList(String singerMid) {List<HotSong> hotSongs = new ArrayList<>();try {for(int i=0; i<singerSongListTotalPage; i++) {String sendUrl = singerSongListUrl.replace("{singermid}", singerMid).replace("{begin}", String.valueOf(30*i)).replace("{num}", String.valueOf(30));String content = HTTPUtil.sendGet(sendUrl).getContent();parseSingerSongList(content, hotSongs, singerMid, i);}//TODOsingerSongListTotalPage=1;} catch (Exception e) {log.error("爬取 {} 歌手下面的歌曲出现错误", singerMid);}List<Song> songList = hotSongSpider.transToPO(hotSongs);hotSongDao.saveOrUpdate(songList);}/*** content* @param content* @param singerMid*/public void parseSingerSongList(String content, List<HotSong> hotSongs, String singerMid, int page) {JSONObject json = JSONObject.parseObject(content);//TODOif(singerSongListTotalPage<=1) {int total = json.getJSONObject("data").getInteger("total");singerSongListTotalPage = (total + 30-1)/30;}JSONArray jsonSongArray = json.getJSONObject("data").getJSONArray("list");try {for(int i=0; i < jsonSongArray.size(); i++) {HotSong song = jsonSongArray.getJSONObject(i).getJSONObject("musicData").toJavaObject(HotSong.class);//获得album_id爬取相应的图片String mid = song.getAlbummid();String albumImg = null;try {//根据url拼接url+album_mid组成完成url,比如https://y.qq.com/n/yqq/album/004PCOKh1RUAqZ.htmlString albumImgUri = MusicConstants.ALBUM_IMG_URI + mid + ".html";//降低爬取速度String html = HTTPUtil.sendGet(albumImgUri).getContent();albumImg = Jsoup.parse(html).getElementById("albumImg").attr("src");} catch (Exception e) {}song.setAlbumImg(albumImg);hotSongs.add(song);}} catch (Exception e) {Map<String , String> errorInfo = new HashMap<>();errorInfo.put("singerMid", singerMid);errorInfo.put("page", String.valueOf(page));errorSingerSongList.add(errorInfo);log.error("爬取 {} 歌手, page: {} 下面的歌曲出现错误", singerMid, page);}}/*** 继续根据歌手列表出现的错误标签和页面爬取歌手* errorSingerList定义的全局变量*/public void spiderErrorSingerSongList() {Map<String, String> errorMap = errorSingerSongList.poll();while(errorMap!= null) {List<HotSong> hotSongs = new ArrayList<>();String singerMid = errorMap.get("singerMid");int page = Integer.parseInt(errorMap.get("page"));try {String sendUrl = singerSongListUrl.replace("{singermid}", singerMid).replace("{begin}", String.valueOf(30*page)).replace("{num}", String.valueOf(30));String content = HTTPUtil.sendGet(sendUrl).getContent();parseSingerSongList(content, hotSongs, singerMid, page);List<Song> songList = hotSongSpider.transToPO(hotSongs);//保存歌曲hotSongDao.saveOrUpdate(songList);errorMap = errorSingerSongList.poll();} catch (Exception e) {Map<String , String> errorInfo = new HashMap<>();errorInfo.put("singerMid", singerMid);errorInfo.put("page", String.valueOf(page));errorSingerSongList.add(errorInfo);}}}}

非常感谢有小伙伴能够重复和测试我的代码,如果在重复中出现问题,或者有关键方法没有引入。请联系我,或者留言。

特别注意:由于水平有限代码肯定存在不足的地方,希望能够指正,那么我将做到更好。

email:chenrui@marsdl.com

以QQ音乐为例子 解析公共接口的json数据相关推荐

  1. php写的接口返回数据的页面,PHP怎么解析 WEBSERVICES接口返回的数据

    PHP如何解析 WEBSERVICES接口返回的数据 WEBSERVICE服务器,他们用.net写了个接口 http://XXX.XXX.XXX.XX/Info.asmx?wsdl 我用PHP调用这个 ...

  2. spring-webmvc-4.1.6 接口返回json数据 中文出现\u0000\u0000\u0000\u0000

    之前搭建开发环境的时候遇到了一个奇怪的现象,使用spring4.1.6的框架,因为spring的升级处理json的jar也跟着升级到了Jackson2.6的rc1版.具体引入的jar如下图所示: 环境 ...

  3. 解析ajax返回的json数据

    问题描述 最近在开发一个音乐小网站的时候,因为返回的数据是多重数组对象(即数组里面嵌套数组),所以不知道如何解析api返回的json数据.返回的json数据格式如下: json总体结构如下: json ...

  4. PHP向第三方接口发送json数据

    2019独角兽企业重金招聘Python工程师标准>>> 开发项目中,遇到需要向第三方接口发送json数据数据的情况,php默认发送数据形式为text,需要告诉第三方接口数据形式为js ...

  5. Java 和 Python 解析动态 key 的 JSON 数据

    一.概述 解析JSON过程中,什么情况都可能遇到.遇到特殊的情况,不会怎么办?肯定不是设计的问题,一定是你的姿势不对. 有这样一种JSON需要解析: {"b3444533f6544" ...

  6. java调用远程 接口_java通过url调用远程接口返回json数据

    java通过url调用远程接口返回json数据,有用户名和密码验证, 转自 https://blog.csdn.net/wanglong1990421/article/details/78815856 ...

  7. 【不务正业系列】爬虫易烊千玺QQ音乐扑通社区“阅读”、“动态”和“成员”数据

    利用亮汤爬虫易烊千玺在QQ音乐扑通社区的"阅读"."动态"和"成员"数据.爬虫效果如下: 爬虫易烊千玺qq音乐数据 一.搭建框架 框架设计如 ...

  8. Java调用接口获取json数据解析后保存到数据库

    文章目录 1.在yml文件中配置自己定义的接口URL 2.在Controller中添加请求方法和路径 3.在Service中添加方法 4.在ServiceImpl中实现方法 今天给大家带来一个调用接口 ...

  9. Winform中怎样使用HttpClient调用http的get和post接口并将接口返回json数据解析为实体类

    场景 需要在Winform的页面初始化之后,调用http的接口,并将返回的json数据 解析,赋值到窗体中的TextBox组件中. 使用接口测试工具测试的接口返回数据如下 注: 博客: 霸道流氓气质的 ...

最新文章

  1. 【OpenCV 】Sobel 导数/Laplace 算子/Canny 边缘检测
  2. 第4章--对链接应用样式
  3. 因特尔计算棒(Intel Movidius Necural Compute)
  4. 程序开发,面试恐惧症_如何克服恐惧并停止讨厌的工作面试
  5. JS与Jquery的事件委托机制
  6. TF目标检测API-Error: Argument must be a dense tensor: range(0, 3) - got shape [3], but wanted []....
  7. python实现蒙特卡洛模拟_蒙特卡洛模拟(Python)深入教程
  8. 浅谈JSP编程的网店管理系统构造
  9. django面试题总结
  10. VB6.0连接Oracle中文乱码
  11. Java集合,泛型,枚举详解
  12. 随机森林原始论文_2020年还需要阅读的10篇人工智能论文(附链接)
  13. 坚果J10的真实流明到底怎么样?坚果J10有哪些缺点
  14. Vue3+file-saver+xlsx 实现 excel 导出
  15. Java 大厂面试必刷题 Day1:何为面向对象编程的思想?面向对象三大特征是什么?
  16. 工作中,掌握这四个说话技巧,再也不用担心自己不会说话
  17. 华清远见-重庆中心-JavaScript知识点梳理
  18. (38)STM32——NRF24L01无线通信
  19. [转]量子力学与心灵的探讨_我是亲民_新浪博客
  20. Java和C语言谁能更胜一筹?

热门文章

  1. gvim 模板(ab命令快速生成常用Verilog模板)
  2. 群晖NAS用迅雷远程下载Xware 1.xxx的进程监视和掉线自动重启
  3. 头脑风暴在计算机中的具体应用,例谈三种头脑风暴样式在综合实践活动中的运用...
  4. 比较原始的QQ大家来找茬的原型
  5. SuperVideo,一款直播,点播,投屏并有的app
  6. python十六进制和十进制相互转换以及由补码求原码
  7. 警方提醒网民警惕网络诈骗七种作案手法
  8. DreamPlan Plus for Mac(家装和景观设计软件)
  9. 华为交换机关机方法_取消华为交换机Console配置密码S2700\3700\5700\6700系列
  10. JVM : 12 面试题:JVM中有哪些垃圾回收算法,每个算法各自的优劣?