国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Python > 正文

Python爬取網(wǎng)易云音樂上評論火爆的歌曲

2019-11-25 16:23:50
字體:
供稿:網(wǎng)友

前言

網(wǎng)易云音樂這款音樂APP本人比較喜歡,用戶量也比較大,而網(wǎng)易云音樂之所以用戶眾多和它的歌曲評論功能密不可分,很多歌曲的評論非常有意思,其中也不乏很多感人的評論。但是,網(wǎng)易云音樂并沒有提供熱評排行榜和按評論排序的功能,沒關(guān)系,本文就使用爬蟲給大家爬一爬網(wǎng)易云音樂上那些熱評的歌曲。

結(jié)果

對過程沒有興趣的童鞋直接看這里啦。

評論數(shù)大于五萬的歌曲排行榜

首先恭喜一下我最喜歡的歌手(之一)周杰倫的《晴天》成為網(wǎng)易云音樂第一首評論數(shù)過百萬的歌曲!

通過結(jié)果發(fā)現(xiàn)目前評論數(shù)過十萬的歌曲正好十首,通過這前十首發(fā)現(xiàn):

  1. 薛之謙現(xiàn)在真的很火啦~
  2. 幾乎都是男歌手啊,男歌手貌似更受歡迎?(別打我),男歌手中周杰倫、薛之謙、許嵩(這三位我都比較喜歡)幾乎占了榜單半壁江山...
  3. 《Fade》電音強(qiáng)勢來襲,很帶感哈(搭配炫邁寫代碼完全停不下來..)

根據(jù)結(jié)果做了網(wǎng)易云音樂歌單 :

評論數(shù)過十萬的歌曲

評論數(shù)過五萬的歌曲

提示: 評論數(shù)過五萬的歌曲 歌單中個別歌曲由于版權(quán)問題暫時下架,暫由其他優(yōu)秀版本代替。

高能預(yù)警:TOP 29 《Lost Rivers》請慎重播放,如果你堅(jiān)持播放請先看評論...

過程

1、觀察網(wǎng)易云音樂官網(wǎng)頁面HTML結(jié)構(gòu)

首頁(http://music.163.com/)

歌單分類頁(http://music.163.com/discover/playlist)。

歌單頁(http://music.163.com/playlist?id=499518394)

歌曲詳情頁(http://music.163.com/song?id=109998)

2、爬取歌曲的ID

通過觀察歌曲詳情頁的URL,我們發(fā)現(xiàn)只要爬取到對應(yīng)歌曲的ID就可以得到它的詳情頁URL,而歌曲的信息都在詳情頁。由此可知只要收集到所有歌曲的ID那么就可以得到所有歌曲的信息啦。而這些ID要從哪里爬呢?從歌單里爬,而歌單在哪爬呢?通過觀察歌單頁的URL我們發(fā)現(xiàn)歌單也有ID,而歌單ID可以從歌單分類頁中爬,好了就這樣爬最終就能收集到所有歌曲的ID了。

3、通過爬取評論數(shù)篩選出符合條件的歌曲

很遺憾的是評論數(shù)雖然也在詳情頁內(nèi),但是網(wǎng)易云音樂做了防爬處理,采用AJAX調(diào)用評論數(shù)API的方式填充評論相關(guān)數(shù)據(jù),由于異步的特性導(dǎo)致我們爬到的頁面中評論數(shù)是空,那么我們就找一找這個API吧,通關(guān)觀察XHR請求發(fā)現(xiàn)是下面這個家伙..


響應(yīng)結(jié)果很豐富呢,所有評論相關(guān)的數(shù)據(jù)都有,不過經(jīng)過觀察發(fā)現(xiàn)這個API是經(jīng)過加密處理的,不過沒關(guān)系...

4、爬取符合條件的歌曲的詳細(xì)信息(名字,歌手等)

這一步就很簡單了,觀察下歌曲詳情頁的HTML很容易就能爬到我們要的名字和歌手信息。

源碼

# encoding=utf8import requestsfrom bs4 import BeautifulSoupimport os, jsonimport base64from Crypto.Cipher import AESfrom prettytable import PrettyTableimport warningswarnings.filterwarnings("ignore")BASE_URL = 'http://music.163.com/'_session = requests.session()# 要匹配大于多少評論數(shù)的歌曲COMMENT_COUNT_LET = 100000class Song(object): def __lt__(self, other): return self.commentCount > other.commentCount# 由于網(wǎng)易云音樂歌曲評論采取AJAX填充的方式所以在HTML上爬不到,需要調(diào)用評論API,而API進(jìn)行了加密處理,下面是相關(guān)解決的方法def aesEncrypt(text, secKey): pad = 16 - len(text) % 16 text = text + pad * chr(pad) encryptor = AES.new(secKey, 2, '0102030405060708') ciphertext = encryptor.encrypt(text) ciphertext = base64.b64encode(ciphertext) return ciphertextdef rsaEncrypt(text, pubKey, modulus): text = text[::-1] rs = int(text.encode('hex'), 16) ** int(pubKey, 16) % int(modulus, 16) return format(rs, 'x').zfill(256)def createSecretKey(size): return (''.join(map(lambda xx: (hex(ord(xx))[2:]), os.urandom(size))))[0:16]# 通過第三方渠道獲取網(wǎng)云音樂的所有歌曲ID# 這里偷了個懶直接從http://grri94kmi4.app.tianmaying.com/songs爬了,這哥們已經(jīng)把官網(wǎng)的歌曲都爬過來了,省事不少# 也可以使用getSongIdList()從官方網(wǎng)站爬,相對比較耗時,但更準(zhǔn)確def getSongIdListBy3Party(): pageMax = 1 # 要爬的頁數(shù),可以根據(jù)需求選擇性設(shè)置頁數(shù) songIdList = [] for page in range(pageMax): url = 'http://grri94kmi4.app.tianmaying.com/songs?page=' + str(page) # print url url.decode('utf-8') soup = BeautifulSoup(_session.get(url).content) # print soup aList = soup.findAll('a', attrs={'target': '_blank'}) for a in aList:  songId = a['href'].split('=')[1]  songIdList.append(songId) return songIdList# 從官網(wǎng)的 發(fā)現(xiàn)-> 歌單 頁面爬取網(wǎng)云音樂的所有歌曲IDdef getSongIdList(): pageMax = 1 # 要爬的頁數(shù),目前一共42頁,爬完42頁需要很久很久,可以根據(jù)需求選擇性設(shè)置頁數(shù) songIdList = [] for i in range(1, pageMax + 1): url = 'http://music.163.com/discover/playlist/?order=hot&cat=全部&limit=35&offset=' + str(i * 35) url.decode('utf-8') soup = BeautifulSoup(_session.get(url).content) aList = soup.findAll('a', attrs={'class': 'tit f-thide s-fc0'}) for a in aList:  uri = a['href']  playListUrl = BASE_URL + uri[1:]  soup = BeautifulSoup(_session.get(playListUrl).content)  ul = soup.find('ul', attrs={'class': 'f-hide'})  for li in ul.findAll('li'):  songId = (li.find('a'))['href'].split('=')[1]  print '爬取歌曲ID成功 -> ' + songId  songIdList.append(songId) # 歌單里難免有重復(fù)的歌曲,去一下重復(fù)的歌曲ID songIdList = list(set(songIdList)) return songIdList# 匹配歌曲的評論數(shù)是否符合要求# let 評論數(shù)大于值def matchSong(songId, let): url = BASE_URL + 'weapi/v1/resource/comments/R_SO_4_' + str(songId) + '/?csrf_token=' headers = {'Cookie': 'appver=1.5.0.75771;', 'Referer': 'http://music.163.com/'} text = {'username': '', 'password': '', 'rememberLogin': 'true'} modulus = '00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7' nonce = '0CoJUm6Qyw8W8jud' pubKey = '010001' text = json.dumps(text) secKey = createSecretKey(16) encText = aesEncrypt(aesEncrypt(text, nonce), secKey) encSecKey = rsaEncrypt(secKey, pubKey, modulus) data = {'params': encText, 'encSecKey': encSecKey} req = requests.post(url, headers=headers, data=data) total = req.json()['total'] if int(total) > let: song = Song() song.id = songId song.commentCount = total return song# 設(shè)置歌曲的信息def setSongInfo(song): url = BASE_URL + 'song?id=' + str(song.id) url.decode('utf-8') soup = BeautifulSoup(_session.get(url).content) strArr = soup.title.string.split(' - ') song.singer = strArr[1] name = strArr[0].encode('utf-8') # 去除歌曲名稱后面()內(nèi)的字,如果不想去除可以注掉下面三行代碼 index = name.find('(') if index > 0: name = name[0:index] song.name = name# 獲取符合條件的歌曲列表def getSongList(): print ' ##正在爬取歌曲編號... ##' # songIdList = getSongIdList() songIdList = getSongIdListBy3Party() print ' ##爬取歌曲編號完成,共計(jì)爬取到' + str(len(songIdList)) + '首##' songList = [] print ' ##正在爬取符合評論數(shù)大于' + str(COMMENT_COUNT_LET) + '的歌曲... ##' for id in songIdList: song = matchSong(id, COMMENT_COUNT_LET) if None != song:  setSongInfo(song)  songList.append(song)  print '成功匹配一首{名稱:', song.name, '-', song.singer, ',評論數(shù):', song.commentCount, '}' print ' ##爬取完成,符合條件的的共計(jì)' + str(len(songList)) + '首##' return songListdef main(): songList = getSongList() # 按評論數(shù)從高往低排序 songList.sort() # 打印結(jié)果 table = PrettyTable([u'排名', u'評論數(shù)', u'歌曲名稱', u'歌手']) for index, song in enumerate(songList): table.add_row([index + 1, song.commentCount, song.name, song.singer]) print table print 'End'if __name__ == '__main__': main()

友情提示:隨著網(wǎng)易云音樂網(wǎng)站結(jié)構(gòu)、接口、加密方式的更換本代碼可能并不能很好的工作,不過過程和原理都是一樣的,這里也只是給大家分享一下這一過程啦。

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作能帶來一定的幫助,如果有疑問大家可以留言交流。

發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 蒙自县| 神池县| 克什克腾旗| 金溪县| 九江县| 利川市| 临猗县| 洛扎县| 合阳县| 集安市| 关岭| 通榆县| 大关县| 修文县| 邯郸市| 宁夏| 方城县| 临泉县| 蓝山县| 许昌县| 双桥区| 庐江县| 屏东市| 昭平县| 台山市| 永善县| 兰考县| 宣汉县| 茌平县| 鄢陵县| 西贡区| 景泰县| 琼结县| 开化县| 白朗县| 兴化市| 崇左市| 临武县| 潜山县| 鄂伦春自治旗| 大城县|