在这次之前学习API的时候发现了一些事情,我利用网易云音乐的API实现了一些简单的歌曲搜索、封面图片的爬去之类的无聊事情。而最近在使用网易云的时候发现自己已经使用网易云整整两年了(顺便思考了一下我的手机为什么装一个APP这么久。连原来的QQ都被卸载了,而网易云依旧在)自己在这两年里成长了许多。而之前在16年初的时候网易云曾针对每一个用户做出一个数据报表:其中包括了播放量TOP10和听歌最久日,最晚听歌使时间和日单循环次数、点赞次数这些东西,当时这个报表其实挺受大家欢迎,而更多的是网易云特有的评论区环境,使用网易云音乐的人大多都是90后,00后。庆幸的是云音乐的讨论区没有成为贴吧知乎那样的气候。但是究竟是怎样的评论吸引着我们这些年轻对着一个 APP放不下手?(不谈音乐,怕大手子 2333),所以就本着这样的目的我尝试去做了:
开始征程吧:
在这之前我有写过关于API的一点东西:API简介和网易云音乐API 其中有提到一些简单的处理办法。而面对大批量的歌曲(目前我听了5800首)这样的方法早已失去其使用的价值和理由,所以得采取新的办法。在这之前我得理清一些东西:首先网易云获取用户听歌量肯定离不开用户ID。而评论的获取则之和歌曲id有关。
从歌单开始:
首先我参考了一下别人写的自用性的文档:https://github.com/darknessomi/musicbox/blob/master/
因为是我听过的歌曲:我现在的歌单数目27个。外加收藏的歌单37个 所以:http://music.163.com/api/user/playlist/?offset=0&limit=64&uid=我的id
这样一来我就拿到了我所有的歌单。现在要做的就是拿到这些歌单中所有的歌曲id。
干这件是之前要做的就是:解析json,拿到list的id号。
# coding=utf-8 import json from urllib import urlopen, quote url = ''http://music.163.com/api/user/playlist/?offset=0&limit=64&uid=97752165'' res = urlopen(url).read().decode(''utf-8'') temp = json.loads(res) lengs = len(temp.get("playlist")) ids = [] for i in range(0,lengs): ids.append(temp.get("playlist")[i].get("id")) print(ids)
这样我就将所有歌单的id存入了ids列表当中,而接下来就是将列表当中的歌曲id和歌曲name获取。
http://music.163.com/api/playlist/detail?id=歌单id 这样一来我就拿到了所有的歌曲:
依旧是处理json数据。
musicid = [] musicname = [] url = ''http://music.163.com/api/playlist/detail?id='' for i in findUserlist(): res = urlopen(url+str(i)).read().decode(''utf-8'') temp = json.loads(res) lengs = len(temp.get("result").get("tracks")) for j in range(0,lengs): musicid.append(temp.get("result").get("tracks")[j].get("id")) musicname.append(temp.get("result").get("tracks")[j].get("name")) print(musicname) print(musicid)
拿到了所有歌曲的id和name(其实只要id就好我,我只是采集评论。name的话用不着的)下一步就是最重要的几部了
获取评论
来到这一步之后我要做的事情就是将所有歌曲的id挨个遍历,查看评论,依旧是解析 json,然后存入数据库当中,最终程序如下:
# coding=utf-8 import json from urllib import urlopen, quote import pymysql conn = pymysql.connect(host=''localhost'',user=''root'', passwd=''******'', db=''nestmusic'',charset="utf8") cur = conn.cursor() cur.execute("USE nestmusic") def store(title, content): cur.execute("INSERT INTO comment (musicname, hotcoment) VALUES (\\"%s\\",\\"%s\\")", (title, content)) cur.connection.commit() def findUserlist(): url = 'http://music.163.com/api/user/playlist/?offset=0&limit=64&uid=97752165' res = urlopen(url).read().decode(''utf-8'') temp = json.loads(res) lengs = len(temp.get("playlist")) ids = [] for i in range(0,lengs): ids.append(temp.get("playlist")[i].get("id")) return ids def findMusiclist(): musicid = [] musicname = [] url = ''http://music.163.com/api/playlist/detail?id='' for i in findUserlist(): res = urlopen(url+str(i)).read().decode(''utf-8'') temp = json.loads(res) lengs = len(temp.get("result").get("tracks")) for j in range(0,lengs): musicid.append(temp.get("result").get("tracks")[j].get("id")) musicname.append(temp.get("result").get("tracks")[j].get("name")) return musicid,musicname def inDb(): url = 'http://music.163.com/api/v1/resource/comments/R_SO_4_' for i in findMusiclist()[0]: res = urlopen(url+str(i)+''/?rid=R_SO_4_''+str(i)+''&\\offset=0&total=fasle&limit=100'').read().decode(''utf-8'') temp = json.loads(res) print(temp.get("hotComments")[0].get("content")) lengs = len(temp.get("hotComments")) for j in range(0,lengs): store(findMusiclist()[1].pop(), temp.get("hotComments")[j].get("content")) try: inDb() finally: cur.close() conn.close()
因为有API访问次数的限制,好像一次采集不完:
但是我不会这样轻易的狗带(滑稽) 而上面的程序依旧存在着巨大的问题,入库其实是无法运行的,由于没有设定请求头的缘故导致很多请求被视为作弊请求,状态码是460,所以我测试了一下单独用浏览器请求发现不受限制:哈哈哈哈
这样一来 一定程度解决了一些问题,但是次数还是不能太频繁,应该是服务器端有次数限制-。而这里最终我把数据处理之后保存为cvs,初级处理也就做完了。
head = {'Host':'music.163.com', 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:56.0) Gecko/20100101 Firefox/56.0', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'Accept-Language': 'zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3', 'Accept-Encoding':'deflate','Connection': 'keep-alive', 'Upgrade-Insecure-Requests' : '1', 'Cache-Control':'max-age=0' } url = 'http://music.163.com/api/v1/resource/comments/R_SO_4_' for i in musicId: uri = url + str(i)+'/?rid=R_SO_4_'+str(i)+'&\\offset=0&total=fasle&limit=100' req = urllib2.Request(uri, None, head) res = urllib2.urlopen(req).read()