项目GitHub地址:https://github.com/sujiujiu/WYYScrapy 评论的API的参考链接:
1、https://github.com/darknessomi/musicbox/wiki/%E7%BD%91%E6%98%93%E4%BA%91%E9%9F%B3%E4%B9%90%E6%96%B0%E7%89%88WebAPI%E5%88%86%E6%9E%90%E3%80%82(这个是从歌单下手的,里面的评论可以参考)
2、http://www.imooc.com/article/17459?block_id=tuijian_wz
3、http://blog.csdn.net/u012104691/article/details/53766045
后面这几篇都讲的比较详细,当时查资料的时候,还查到另外一种写法,就是里面有一堆命名是first_param什么的,看得头晕眼花,然后当时测试似乎也没有成功,建议用现在的这种就好了。 基本模式就是这样:
图片代码来自:来自https://github.com/darknessomi/musicbox/wiki/%E7%BD%91%E6%98%93%E4%BA%91%E9%9F%B3%E4%B9%90%E6%96%B0%E7%89%88WebAPI%E5%88%86%E6%9E%90%E3%80%82 因为专辑和歌曲都有评论,所以我专门将它写成了个类,后面直接调用就可以了。 # -*-coding:utf-8-*-import osimport reimport sysimport jsonimport base64import binasciiimport hashlibimport requestsfrom Crypto.Cipher import AESclass CommentCrawl(object): '''评论的API封装成一个类,直接传入评论的API,再调用函数get_song_comment()和get_album_comment()即可分别获取歌曲和专辑的评论信息 ''' def __init__(self,comment_url): self.comment_url = comment_url self.headers = { "Referer":"http://music.163.com", "User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3067.6 Safari/537.36", } def createSecretKey(self,size): '''生成长度为16的随机字符串作为密钥secKey ''' return (''.join(map(lambda xx: (hex(ord(xx))[2:]), os.urandom(size))))[0:16] def AES_encrypt(self,text, secKey): '''进行AES加密 ''' pad = 16 - len(text) % 16 text = text + pad * chr(pad) encryptor = AES.new(secKey, 2, '0102030405060708') encrypt_text = encryptor.encrypt(text.encode()) encrypt_text = base64.b64encode(encrypt_text) return encrypt_text def rsaEncrypt(self, text, pubKey, modulus): '''进行RSA加密 ''' text = text[::-1] rs = int(text.encode('hex'), 16) ** int(pubKey, 16) % int(modulus, 16) return format(rs, 'x').zfill(256) def encrypted_request(self, text): '''将明文text进行两次AES加密获得密文encText, 因为secKey是在客户端上生成的,所以还需要对其进行RSA加密再传给服务端。 ''' pubKey = '010001' modulus = '00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7' nonce = '0CoJUm6Qyw8W8jud' text = json.dumps(text) secKey = self.createSecretKey(16) encText = self.AES_encrypt(self.AES_encrypt(text, nonce), secKey) encSecKey = self.rsaEncrypt(secKey, pubKey, modulus) data = { 'params': encText, 'encSecKey': encSecKey } return data def get_post_req(self, url, data): try: req = requests.post(url, headers=self.headers, data=data) except Exception,e: # dosomething print url,e # return None return req.json() def get_offset(self, offset=0): '''偏移量 ''' if offset == 0: text = {'rid':'', 'offset':'0', 'total':'true', 'limit':'20', 'csrf_token':''} else: text = {'rid':'', 'offset':'%s' % offset, 'total':'false', 'limit':'20', 'csrf_token':''} return text def get_json_data(self,url,offset): '''json 格式的评论 ''' text = self.get_offset(offset) data = self.encrypted_request(text) json_text = self.get_post_req(url, data) return json_text def get_song_comment(self): '''某首歌下全部评论 ''' comment_info = [] data = self.get_json_data(self.comment_url,offset=0) comment_count = data['total'] if comment_count: comment_info.append(data) if comment_count > 20: for offset in range(20,int(comment_count),20): comment = self.get_json_data(self.comment_url,offset=offset) comment_info.append(comment) return comment_info def get_album_comment(self,comment_count): '''某专辑下全部评论 ''' album_comment_info = [] if comment_count: for offset in range(0,int(comment_count),20): comment = self.get_json_data(self.comment_url,offset=offset) album_comment_info.append(comment) return album_comment_info- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
重复的地方我就不赘述了,最后两个地方我之所以分开写,是因为专辑的评论数可以从专辑信息里获取,但歌曲评论数从专辑列表信息里获取不到,只能先爬取它第一页的json数据,它里面的total就是评论总数,然后再做后面的处理。 评论的API: # 1、专辑:comment_url = 'http://music.163.com/weapi/v1/resource/comments/R_AL_3_%s?csrf_token=' % album_id# 2、歌曲:comment_url = 'http://music.163.com/weapi/v1/resource/comments/R_SO_4_%s?csrf_token=' % song_id然后将comment_url 作为参数传入上面封装的那个类里即可,不同的是专辑还需先获取专辑评论的数量。
所有的分析都结束了,接下来的代码自己写吧。
|