Python 获取 网易云音乐热门评论(python2/python3代码)
為方便學習,主要內容轉自:http://www.cnblogs.com/lyrichu/p/6635798.html,感謝原作,如有侵權,聯系刪除
獲取文本的方式有很多,比如從網上下載現成的文本文檔,或者通過第三方提供的API進行獲取數據。但是有的時候我們想要的數據并不能直接獲取,因為并不提供直接的下載渠道或者API供我們獲取數據。那么這個時候該怎么辦呢?有一種比較好的辦法是通過網絡爬蟲,即編寫計算機程序偽裝成用戶去獲得想要的數據。利用計算機的高效,我們可以輕松快速地獲取數據。
???? 那么該如何寫一個爬蟲呢?有很多種語言都可以寫爬蟲,比如Java,php,python 等,我個人比較喜歡使用python。因為python不僅有著內置的功能強大的網絡庫,還有諸多優秀的第三方庫,別人直接造好了輪子,我們直接拿過來用就可以了,這為寫爬蟲帶來了極大的方便。不夸張地說,使用不到10行python代碼其實就可以寫一個小小的爬蟲,而使用其他的語言可以要多寫很多代碼,簡潔易懂正是python的巨大的優勢。
??? 好了廢話不多說,進入今天的正題。最近幾年網易云音樂火了起來,我自己就是網易云音樂的用戶,用了幾年了。以前用的是QQ音樂和酷狗,通過我自己的親身經歷來看,我覺得網易云音樂最優特色的就是其精準的歌曲推薦和獨具特色的用戶評論(鄭重聲明!!!這不是軟文,非廣告!!!僅代表個人觀點,非喜勿噴!)。經常一首歌曲下面會有一些被點贊眾多的神評論。加上前些日子網易云音樂將精選用戶評論搬上了地鐵,網易云音樂的評論又火了一把。所以我想對網易云的評論進行分析,發現其中的規律,特別是分析一些熱評具有什么共同的特點。帶著這個目的,我開始了對網易云評論的抓取工作。
???? python內置了兩個網絡庫urllib和urllib2,但是這兩個庫使用起來不是特別方便,所以在這里我們使用一個廣受好評的第三方庫requests。使用requests只用很少的幾行代碼就可以實現設置代理,模擬登陸等比較復雜的爬蟲工作。如果已經安裝pip的話,直接使用pip install requests 即可安裝。中文文檔地址在此http://docs.python-requests.org/zh_CN/latest/user/quickstart.html,大家有什么問題可以自行參考官方文檔,上面會有非常詳細的介紹。至于urllib和urllib2這兩個庫也是比較有用的,以后如果有機會我會再給大家介紹一下。
???? 在正式開始介紹爬蟲之前,首先來說一下爬蟲的基本工作原理,我們知道我們打開瀏覽器訪問某個網址本質上是向服務器發送了一定的請求,服務器在收到我們的請求之后,會根據我們的請求返回數據,然后通過瀏覽器將這些數據解析好,呈現在我們的面前。如果我們使用代碼的話,就要跳過瀏覽器的這個步驟,直接向服務器發送一定的數據,然后再取回服務器返回的數據,提取出我們想要的信息。但是問題是,有的時候服務器需要對我們發送的請求進行校驗,如果它認為我們的請求是非法的,就會不返回數據,或者返回錯誤的數據。所以為了避免發生這種情況,我們有的時候需要把程序偽裝成一個正常的用戶,以便順利得到服務器的回應。如何偽裝呢?這就要看用戶通過瀏覽器訪問一個網頁與我們通過程序訪問一個網頁之間的區別。通常來說,我們通過瀏覽器訪問一個網頁,除了發送訪問的url之外,還會給服務發送額外的信息,比如headers(頭部信息)等,這就相當于是請求的身份證明,服務器看到了這些數據,就會知道我們是通過正常的瀏覽器訪問的,就會乖乖地返回數據給我們了。所以我們程序就得像瀏覽器一樣,在發送請求的時候,帶上這些標志著我們身份的信息,這樣就能順利拿到數據。有的時候,我們必須在登錄狀態下才能得到一些數據,所以我們必須要模擬登錄。本質上來說,通過瀏覽器登錄就是post一些表單信息給服務器(包括用戶名,密碼等信息),服務器校驗之后我們就可以順利登錄了,利用程序也是一樣,瀏覽器post什么數據,我們原樣發送就可以了。關于模擬登錄,我后面會專門介紹一下。當然事情有的時候也不會這么順利,因為有些網站設置了反爬措施,比如如果訪問過快,有時候會被封ip(典型的比如豆瓣)。這個時候我們還得要設置代理服務器,即變更我們的ip地址,如果一個ip被封了,就換另外一個ip,具體怎么做,這些話題以后慢慢再說。
???? 最后,再介紹一個我認為在寫爬蟲過程中非常有用的一個小技巧。如果你在使用火狐瀏覽器或者chrome的話,也許你會注意到有一個叫作開發者工具(chrome)或者web控制臺(firefox)的地方。這個工具非常有用,因為利用它,我們可以清楚地看到在訪問一個網站的過程中,瀏覽器到底發送了什么信息,服務器究竟返回了什么信息,這些信息是我們寫爬蟲的關鍵所在。下面你就會看到它的巨大用處。
????? --------------------------------------------------------------正式開始的分割線------------------------------------------------------------------------
??? 首先打開網易云音樂的網頁版,隨便選擇一首歌曲打開它的網頁,這里我以周杰倫的《晴天》為例。如下圖1
圖1
???????? 接下來打開web控制臺(chrom的話打開開發者工具,如果是其他瀏覽器應該也是類似),如下圖2
圖2
然后這個時候我們需要點選網絡,清除所有的信息,然后點擊重新發送(相當于是刷新瀏覽器),這樣我們就可以直觀看到瀏覽器發送了什么信息以及服務器回應了什么信息。如下圖3
圖3
刷新之后得到的數據如下圖4所示:
圖4
可以看到瀏覽器發送了非常多的信息,那么哪一個才是我們想要的呢?這里我們可以通過狀態碼做一個初步的判斷,status code(狀態碼)標志了服務器請求的狀態,這里狀態碼為200即表示請求正常,而304則表示不正常(狀態碼種類非常多,如果要想詳細了解可以自行搜索,這里不說304具體的含義了)。所以我們一般只用看狀態碼為200的請求就可以了,還有就是,我們可以通過右邊欄的預覽來粗略觀察服務器返回了什么信息(或者查看響應)。如下圖5所示:
圖5
通過這兩種方法結合一般我們就可以快速找到我們想要分析的請求。注意圖5中的請求網址一欄即是我們想要請求的網址,請求的方法有兩種:get和post,還有一個需要重點關注的就是請求頭,里面包含了user-Agent(客戶端信息),refrence(從何處跳轉過來)等多種信息,一般無論是get還是post方法我們都會把頭部信息帶上。頭部信息如下圖6所示:
圖6
另外還需要注意的是:get請求一般就直接把請求的參數以?parameter1=value1¶meter2=value2 等這樣的形式發送了,所以不需要帶上額外的請求參數,而post請求則一般需要帶上額外的參數,而不直接把參數放在url當中,所以有的時候我們還需要關注參數這一欄。經過仔細尋找,我們終于找到原來與評論相關的請求在http://music.163.com/weapi/v1/resource/comments/R_SO_4_186016?csrf_token=? 這個請求當中,如下圖7所示:
圖7
點開這個請求,我們發現它是一個post請求,請求的參數有兩個,一個是params,還有一個是encSecKey,這兩個參數的值非常的長,感覺應該像是加密過的。如下圖8所示:
圖8
服務器返回的和評論相關的數據為json格式的,里面含有非常豐富的信息(比如有關評論者的信息,評論日期,點贊數,評論內容等等),如下圖9所示:(其實hotComments為熱門評論,comments為評論數組)
圖9
????? 至此,我們已經確定了方向了,即只需要確定params和encSecKey這兩個參數值即可,這個問題困擾了我一下午,我弄了很久也沒有搞清楚這兩個參數的加密方式,但是我發現了一個規律,http://music.163.com/weapi/v1/resource/comments/R_SO_4_186016?csrf_token= 中 R_SO_4_后面的數字就是這首歌的id值,而對于不同的歌曲的param和encSecKey值,如果把一首歌比如A的這兩個參數值傳給B這首歌,那么對于相同的頁數,這種參數是通用的,即A的第一頁的兩個參數值傳給其他任何一首歌的兩個參數,都可以獲得相應歌曲的第一頁的評論,對于第二頁,第三頁等也是類似。但是遺憾的是,不同的頁數參數是不同的,這種辦法只能抓取有限的幾頁(當然抓取評論總數和熱門評論已經足夠了),如果要想抓取全部數據,就必須搞明白這兩個參數值的加密方式。以為沒有搞明白,昨天晚上我帶著這個問題去知乎搜索了一下,居然真的被我找到了答案。在這個問題https://www.zhihu.com/question/36081767 下,@平胸小仙女 這位知友詳細說明了如何破解這兩個參數的加密過程,我研究了一下,發現還是有點小復雜的,按照他寫的方法,我改動了一下,就成功得到了全部的評論。這里要對@平胸小仙女(個人主頁 https://www.zhihu.com/people/luocaodan/answers)表示感謝。如果大家對于破解參數加密有興趣的話,可以去直接參考原帖,地址是:https://www.zhihu.com/question/36081767。
?????? 到此為止,如何抓取網易云音樂的評論全部數據就全部講完了。按照慣例,最后上代碼,親測有效:
1 #!/usr/bin/env python2.7 2 # -*- coding: utf-8 -*- 3 # @Time : 2017/3/28 8:46 4 # @Author : Lyrichu 5 # @Email : 919987476@qq.com 6 # @File : NetCloud_spider3.py 7 ''' 8 @Description: 9 網易云音樂評論爬蟲,可以完整爬取整個評論 10 部分參考了@平胸小仙女的文章(地址:https://www.zhihu.com/question/36081767) 11 post加密部分也給出了,可以參考原帖: 12 作者:平胸小仙女 13 鏈接:https://www.zhihu.com/question/36081767/answer/140287795 14 來源:知乎 15 ''' 16 from Crypto.Cipher import AES 17 import base64 18 import requests 19 import json 20 import codecs 21 import time 22 23 # 頭部信息 24 headers = { 25 'Host':"music.163.com", 26 'Accept-Language':"zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3", 27 'Accept-Encoding':"gzip, deflate", 28 'Content-Type':"application/x-www-form-urlencoded", 29 'Cookie':"_ntes_nnid=754361b04b121e078dee797cdb30e0fd,1486026808627; _ntes_nuid=754361b04b121e078dee797cdb30e0fd; JSESSIONID-WYYY=yfqt9ofhY%5CIYNkXW71TqY5OtSZyjE%2FoswGgtl4dMv3Oa7%5CQ50T%2FVaee%2FMSsCifHE0TGtRMYhSPpr20i%5CRO%2BO%2B9pbbJnrUvGzkibhNqw3Tlgn%5Coil%2FrW7zFZZWSA3K9gD77MPSVH6fnv5hIT8ms70MNB3CxK5r3ecj3tFMlWFbFOZmGw%5C%3A1490677541180; _iuqxldmzr_=32; vjuids=c8ca7976.15a029d006a.0.51373751e63af8; vjlast=1486102528.1490172479.21; __gads=ID=a9eed5e3cae4d252:T=1486102537:S=ALNI_Mb5XX2vlkjsiU5cIy91-ToUDoFxIw; vinfo_n_f_l_n3=411a2def7f75a62e.1.1.1486349441669.1486349607905.1490173828142; P_INFO=m15527594439@163.com|1489375076|1|study|00&99|null&null&null#hub&420100#10#0#0|155439&1|study_client|15527594439@163.com; NTES_CMT_USER_INFO=84794134%7Cm155****4439%7Chttps%3A%2F%2Fsimg.ws.126.net%2Fe%2Fimg5.cache.netease.com%2Ftie%2Fimages%2Fyun%2Fphoto_default_62.png.39x39.100.jpg%7Cfalse%7CbTE1NTI3NTk0NDM5QDE2My5jb20%3D; usertrack=c+5+hljHgU0T1FDmA66MAg==; Province=027; City=027; _ga=GA1.2.1549851014.1489469781; __utma=94650624.1549851014.1489469781.1490664577.1490672820.8; __utmc=94650624; __utmz=94650624.1490661822.6.2.utmcsr=baidu|utmccn=(organic)|utmcmd=organic; playerid=81568911; __utmb=94650624.23.10.1490672820", 30 'Connection':"keep-alive", 31 'Referer':'http://music.163.com/' 32 } 33 # 設置代理服務器 34 proxies= { 35 'http:':'http://121.232.146.184', 36 'https:':'https://144.255.48.197' 37 } 38 39 # offset的取值為:(評論頁數-1)*20,total第一頁為true,其余頁為false 40 # first_param = '{rid:"", offset:"0", total:"true", limit:"20", csrf_token:""}' # 第一個參數 41 second_param = "010001" # 第二個參數 42 # 第三個參數 43 third_param = "00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7" 44 # 第四個參數 45 forth_param = "0CoJUm6Qyw8W8jud" 46 47 # 獲取參數 48 def get_params(page): # page為傳入頁數 49 iv = "0102030405060708" 50 first_key = forth_param 51 second_key = 16 * 'F' 52 if(page == 1): # 如果為第一頁 53 first_param = '{rid:"", offset:"0", total:"true", limit:"20", csrf_token:""}' 54 h_encText = AES_encrypt(first_param, first_key, iv) 55 else: 56 offset = str((page-1)*20) 57 first_param = '{rid:"", offset:"%s", total:"%s", limit:"20", csrf_token:""}' %(offset,'false') 58 h_encText = AES_encrypt(first_param, first_key, iv) 59 h_encText = AES_encrypt(h_encText, second_key, iv) 60 return h_encText 61 62 # 獲取 encSecKey 63 def get_encSecKey(): 64 encSecKey = "257348aecb5e556c066de214e531faadd1c55d814f9be95fd06d6bff9f4c7a41f831f6394d5a3fd2e3881736d94a02ca919d952872e7d0a50ebfa1769a7a62d512f5f1ca21aec60bc3819a9c3ffca5eca9a0dba6d6f7249b06f5965ecfff3695b54e1c28f3f624750ed39e7de08fc8493242e26dbc4484a01c76f739e135637c" 65 return encSecKey 66 67 68 # 解密過程 69 def AES_encrypt(text, key, iv): 70 pad = 16 - len(text) % 16 71 text = text + pad * chr(pad) 72 encryptor = AES.new(key, AES.MODE_CBC, iv) 73 encrypt_text = encryptor.encrypt(text) 74 encrypt_text = base64.b64encode(encrypt_text) 75 return encrypt_text 76 77 # 獲得評論json數據 78 def get_json(url, params, encSecKey): 79 data = { 80 "params": params, 81 "encSecKey": encSecKey 82 } 83 response = requests.post(url, headers=headers, data=data,proxies = proxies) 84 return response.content 85 86 # 抓取熱門評論,返回熱評列表 87 def get_hot_comments(url): 88 hot_comments_list = [] 89 hot_comments_list.append(u"用戶ID 用戶昵稱 用戶頭像地址 評論時間 點贊總數 評論內容\n") 90 params = get_params(1) # 第一頁 91 encSecKey = get_encSecKey() 92 json_text = get_json(url,params,encSecKey) 93 json_dict = json.loads(json_text) 94 hot_comments = json_dict['hotComments'] # 熱門評論 95 print("共有%d條熱門評論!" % len(hot_comments)) 96 for item in hot_comments: 97 comment = item['content'] # 評論內容 98 likedCount = item['likedCount'] # 點贊總數 99 comment_time = item['time'] # 評論時間(時間戳) 100 userID = item['user']['userID'] # 評論者id 101 nickname = item['user']['nickname'] # 昵稱 102 avatarUrl = item['user']['avatarUrl'] # 頭像地址 103 comment_info = userID + " " + nickname + " " + avatarUrl + " " + comment_time + " " + likedCount + " " + comment + u"\n" 104 hot_comments_list.append(comment_info) 105 return hot_comments_list 106 107 # 抓取某一首歌的全部評論 108 def get_all_comments(url): 109 all_comments_list = [] # 存放所有評論 110 all_comments_list.append(u"用戶ID 用戶昵稱 用戶頭像地址 評論時間 點贊總數 評論內容\n") # 頭部信息 111 params = get_params(1) 112 encSecKey = get_encSecKey() 113 json_text = get_json(url,params,encSecKey) 114 json_dict = json.loads(json_text) 115 comments_num = int(json_dict['total']) 116 if(comments_num % 20 == 0): 117 page = comments_num / 20 118 else: 119 page = int(comments_num / 20) + 1 120 print("共有%d頁評論!" % page) 121 for i in range(page): # 逐頁抓取 122 params = get_params(i+1) 123 encSecKey = get_encSecKey() 124 json_text = get_json(url,params,encSecKey) 125 json_dict = json.loads(json_text) 126 if i == 0: 127 print("共有%d條評論!" % comments_num) # 全部評論總數 128 for item in json_dict['comments']: 129 comment = item['content'] # 評論內容 130 likedCount = item['likedCount'] # 點贊總數 131 comment_time = item['time'] # 評論時間(時間戳) 132 userID = item['user']['userId'] # 評論者id 133 nickname = item['user']['nickname'] # 昵稱 134 avatarUrl = item['user']['avatarUrl'] # 頭像地址 135 comment_info = unicode(userID) + u" " + nickname + u" " + avatarUrl + u" " + unicode(comment_time) + u" " + unicode(likedCount) + u" " + comment + u"\n" 136 all_comments_list.append(comment_info) 137 print("第%d頁抓取完畢!" % (i+1)) 138 return all_comments_list 139 140 141 # 將評論寫入文本文件 142 def save_to_file(list,filename): 143 with codecs.open(filename,'a',encoding='utf-8') as f: 144 f.writelines(list) 145 print("寫入文件成功!") 146 147 if __name__ == "__main__": 148 start_time = time.time() # 開始時間 149 url = "http://music.163.com/weapi/v1/resource/comments/R_SO_4_186016/?csrf_token=" 150 filename = u"晴天.txt" 151 all_comments_list = get_all_comments(url) 152 save_to_file(all_comments_list,filename) 153 end_time = time.time() #結束時間 154 print("程序耗時%f秒." % (end_time - start_time))我利用上述代碼跑了一下,抓了兩首周杰倫的熱門歌曲《晴天》(有130多萬評論)和《告白氣球》(有20多萬評論),前者跑了大概有20多分鐘,后者有6600多秒(也就是將近2個小時),截圖如下:
注意我是按照空格來分隔的,每一行分別有用戶ID?用戶昵稱 用戶頭像地址 評論時間 點贊總數 評論內容?這些內容。我將這兩個txt文件上傳到百度云了,對數據感興趣的同學可以直接下載進行文本分析,地址為:《晴天》(http://pan.baidu.com/s/1boBglfp),《告白氣球》(http://pan.baidu.com/s/1o8O7k1s),或者自己跑一下代碼抓取一下也是可以的(注意不要開太多線程給網易云的服務器太大壓力哦~~中間有一段時間服務器返回數據特別慢,不知道是不是限制訪問了,后來又好了)。我后面也許會自己去對評論數據進行可視化分析,敬請期待!
====================================================================================================================================
這是分割線:由于原作的代碼是python2實現的,python3需修改些細節(主要是編碼問題)編碼問題參考:http://blog.csdn.net/taotiezhengfeng/article/details/73550669
? ? ?http://blog.csdn.net/taotiezhengfeng/article/details/73550707
下面是python3的代碼實現:
==================================================================================================
# coding: utf-8# ### 爬取網易音樂的評論# In[1]:from Crypto.Cipher import AES import base64 import requests import json import codecs import time # 頭部信息 headers = {'Host':"music.163.com",'Accept-Language':"zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3",'Accept-Encoding':"gzip, deflate",'Content-Type':"application/x-www-form-urlencoded",'Cookie':"_ntes_nnid=754361b04b121e078dee797cdb30e0fd,1486026808627; _ntes_nuid=754361b04b121e078dee797cdb30e0fd; JSESSIONID-WYYY=yfqt9ofhY%5CIYNkXW71TqY5OtSZyjE%2FoswGgtl4dMv3Oa7%5CQ50T%2FVaee%2FMSsCifHE0TG tRMYhSPpr20i%5CRO%2BO%2B9pbbJnrUvGzkibhNqw3Tlgn%5Coil%2FrW7zFZZWSA3K9gD77MPSVH6fnv5hIT8ms70MNB3CxK5r3ecj3tFMlWFbFOZmGw%5C%3A1490677541180; _iuqxldmzr_=32; vjuids=c8ca7976.15a029d006a.0.51373751e63af8;vjlast=1486102528.1490172479.21; __gads=ID=a9eed5e3cae4d252:T=1486102537:S=ALNI_Mb5XX2vlkjsiU5cIy91-ToUDoFxIw; vinfo_n_f_l_n3=411a2def7f75a62e.1.1.1486349441669.1486349607905.1490173828142; P_INFO=m15527594439@163.com|1489375076|1|study|00&99|null&null&null#hub&420100#10#0#0|155439&1|study_client|15527594439@163.com; NTES_CMT_USER_INFO=84794134%7Cm155****4439%7Chttps%3A%2F%2Fsimg.ws.126.net%2Fe%2Fimg5.cache.netease.com%2Ftie%2Fimages %2Fyun%2Fphoto_default_62.png.39x39.100.jpg%7Cfalse%7CbTE1NTI3NTk0NDM5QDE2My5jb20%3D; usertrack=c+5+hljHgU0T1FDmA66MAg==; Province=027; City=027; _ga=GA1.2.1549851014.1489469781; __utma=94650624.1549851014.1489469781.1490664577.1490672820.8; __utmc=94650624; __utmz=94650624.1490661822.6.2.utmcsr=baidu|utmccn=(organic)|utmcmd=organic; playerid=81568911; __utmb=94650624.23.10.1490672820", 'Connection':"keep-alive",'Referer':'http://music.163.com/' }# 設置代理服務器 proxies= {'http:':'http://121.232.146.184','https:':'https://144.255.48.197'}# offset的取值為:(評論頁數-1)*20,total第一頁為true,其余頁為false # first_param = '{rid:"", offset:"0", total:"true", limit:"20", csrf_token:""}' # 第一個參數 second_param = "010001" # 第二個參數# 第三個參數 third_param = "00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e 0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7"# 第四個參數 forth_param = "0CoJUm6Qyw8W8jud" # 解密過程 def AES_encrypt(text, key, iv):pad = 16 - len(text) % 16text = text + pad * chr(pad) # chr(pad)是str屬性 # text = text + (pad * chr(pad)).decode('utf-8')encryptor = AES.new(key, AES.MODE_CBC, iv)encrypt_text = encryptor.encrypt(text)encrypt_text = base64.b64encode(encrypt_text)# 所得encrypt_text為 bytes 類型encrypt_text = bytes.decode(encrypt_text) # 將bytes類型轉換為str類型 return encrypt_text # 獲取參數 def get_params(page): # page為傳入頁數iv = "0102030405060708"first_key = forth_paramsecond_key = 16 * 'F'if(page == 1): # 如果為第一頁first_param = '{rid:"", offset:"0", total:"true", limit:"20", csrf_token:""}'h_encText = AES_encrypt(first_param, first_key, iv) # print(type(h_encText))else:offset = str((page-1)*20)first_param = '{rid:"", offset:"%s", total:"%s", limit:"20", csrf_token:""}' %(offset,'false')h_encText = AES_encrypt(first_param, first_key, iv) # print(type(h_encText))h_encText = AES_encrypt(h_encText, second_key, iv)return h_encText # 獲取 encSecKey def get_encSecKey():encSecKey = "257348aecb5e556c066de214e531faadd1c55d814f9be95fd06d6bff9f4c7a41f831f6394d5a3fd2e3881736d94a02ca919d952872e7d0a50ebfa1769a 7a62d512f5f1ca21aec60bc3819a9c3ffca5eca9a0dba6d6f7249b06f5965ecfff3695b54e1c28f3f624750ed39e7de08fc8493242e26dbc4484a01c76f739e135637c" return encSecKey # 獲得評論json數據 def get_json(url, params, encSecKey):data = {"params": params,"encSecKey": encSecKey}response = requests.post(url, headers=headers, data=data,proxies = proxies) # return response.contentreturn bytes.decode(response.content) # 抓取熱門評論,返回熱評列表 def get_hot_comments(url):hot_comments_list = []headString = '用戶昵稱'+ '\t\t' + '點贊總數'+ '\t\t\t\t' + '評論內容' + '\r\n'hot_comments_list.append(headString) # 頭部信息params = get_params(1) # 第一頁encSecKey = get_encSecKey()json_text = get_json(url,params,encSecKey)json_dict = json.loads(json_text)hot_comments = json_dict['hotComments'] # 熱門評論print("共有%d條熱門評論!\n" % len(hot_comments))count = 1for item in hot_comments:comment = item['content'] # 評論內容likedCount = item['likedCount'] # 點贊總數comment_time = item['time'] # 評論時間(時間戳)userID = item['user']['userId'] # 評論者idnickname = item['user']['nickname'] # 昵稱avatarUrl = item['user']['avatarUrl'] # 頭像地址comment_info = '\r\n'+ str(count) +'.'+ nickname + "\t\t"+ '(' + str(likedCount) + ')'+"\t\t" + comment + "\r\n"count = count+1hot_comments_list.append(comment_info)return hot_comments_list # 抓取某一首歌的點贊數超過 flag 的全部評論 ## Note: # 如果一首歌的評論太多,抓取超過7000頁可能會被封IP,親測被封 # 沒必要取所有評論,只需要看點贊數超過一定的評論即可 # 這里設置獲取歌詞的點贊數,在所有評論中,只有點贊數超過 flag(默認為1000) 的歌詞才被抓取def get_some_comments(url,flag = 1000):all_comments_list = [] # 存放所有評論headString = '用戶昵稱'+ '\t\t' + '點贊總數'+ '\t\t\t\t' + '評論內容' + '\r\n'all_comments_list.append(headString) # 頭部信息params = get_params(1)encSecKey = get_encSecKey()json_text = get_json(url,params,encSecKey)json_dict = json.loads(json_text)comments_num = int(json_dict['total'])if(comments_num % 20 == 0):page = comments_num / 20else:page = int(comments_num / 20) + 1print("共有%d頁評論!\n" % page)for i in range(page): # 逐頁抓取params = get_params(i+1)encSecKey = get_encSecKey()json_text = get_json(url,params,encSecKey)json_dict = json.loads(json_text)if i == 0:print("共有%d條評論!\n" % comments_num) # 全部評論總數print("我只想抓取點贊數大于 %d 的評論!\n" % flag)for item in json_dict['comments']:likedCount = item['likedCount'] # 點贊總數if likedCount > flag:comment = item['content'] # 評論內容nickname = item['user']['nickname'] # 昵稱comment_info = '\r\n'+ nickname + "\t\t"+ '(' + str(likedCount) + ')'+"\t\t" + comment + "\r\n"all_comments_list.append(comment_info) # print("第%d頁抓取完畢!" % (i+1))return all_comments_list # 抓取某一首歌的全部評論 def get_all_comments(url):all_comments_list = [] # 存放所有評論headString = '用戶昵稱'+ '\t\t' + '點贊總數'+ '\t\t\t\t' + '評論內容' + '\r\n'all_comments_list.append(headString) # 頭部信息params = get_params(1)encSecKey = get_encSecKey()json_text = get_json(url,params,encSecKey)json_dict = json.loads(json_text)comments_num = int(json_dict['total'])if(comments_num % 20 == 0):page = comments_num / 20else:page = int(comments_num / 20) + 1print("共有%d頁評論!\n" % page)for i in range(page): # 逐頁抓取params = get_params(i+1)encSecKey = get_encSecKey()json_text = get_json(url,params,encSecKey)json_dict = json.loads(json_text)if i == 0:print("共有%d條評論!\n" % comments_num) # 全部評論總數for item in json_dict['comments']:comment = item['content'] # 評論內容likedCount = item['likedCount'] # 點贊總數nickname = item['user']['nickname'] # 昵稱comment_info = '\r\n'+ nickname + "\t\t"+ '(' + str(likedCount) + ')'+"\t\t" + comment + "\r\n"all_comments_list.append(comment_info) # print("第%d頁抓取完畢!" % (i+1))return all_comments_list # 將評論寫入文本文件 def save_to_file(list,filename):with codecs.open(filename,'a',encoding='utf-8') as f:f.writelines(list)print("寫入文件成功!") if __name__ == "__main__":start_time = time.time() # 開始時間# Note!! 這兒修改歌詞ID: R_SO_4_該歌的ID值 (如481535136,在該歌的網址上有該ID值)url = "http://music.163.com/weapi/v1/resource/comments/R_SO_4_471385043/?csrf_token="filename = u"5曖昧_hot.txt" # 修改歌名# 選擇所需的評論抓取方式:# 方式1:抓取最熱門的評論all_comments_list = get_hot_comments(url)# 方式2:瀏覽所有評論,只獲取點贊數數大于500的評論,評論超50萬時不建議開啟,容易被封IP# all_comments_list = get_some_comments(url,500)# 方式3: 獲取本歌的所有評論,評論超50萬時不建議開啟,容易被封IP# get_all_comments(url)save_to_file(all_comments_list,filename) # 保存抓取的文件end_time = time.time() #結束時間print("程序耗時%f秒." % (end_time - start_time)) 以上代碼在python3中運行正確
總結
以上是生活随笔為你收集整理的Python 获取 网易云音乐热门评论(python2/python3代码)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 米家对讲机_可以与手机互动的对讲机,小米
- 下一篇: GBK 和 UTF8编码