又到了清明時節,用python爬取了網易雲音樂《清明雨上》的評論,統計詞頻和繪製詞雲圖,記錄過程當中遇到一些問題 ####爬取網易雲音樂的評論 一開始是按照常規思路,分析網頁ajax的傳參狀況。看到參數都是加密過的,在網上參考別人以前爬蟲的思路。發現陸續有人用模擬傳參,本身加密參數來實現,主要用python和js版本的。我嘗試了幾回,加密過程有問題沒解決。後來忽然看到有人提到了一個get請求獲取評論的url,實測能夠用,估計是傳參以後,實際調用的內部接口。
http://music.163.com/api/v1/resource/comments/R_SO_4_167882?limit=20&offset=0
嘗試以後發現能夠直接調用,那麼就簡單多了
下面截取部分爬取的內容python
2014-11-25 20:01:18 年輕的記憶:高一聽的歌,如今都大三了,時間好快 2016-03-26 19:15:38 這個暱稱不少人用過:東瓶西鏡放,是安徽古建築習俗。客廳東部放瓶子,西邊放鏡子,意爲終平生(瓶)靜(鏡)。[憨笑] 2016-06-28 17:04:09 Gorlomi:周杰倫的中國風是宮廷的,有傳統的氣息;許嵩的中國風是江南的,有梅雨的味道。 2016-03-16 16:48:20 樹下蝸牛殼:半城煙沙半城血,清明雨上客怎眠。千百度裏尋伊人,不見當年廬州月。 2015-01-05 20:18:57 等煙雨天青青:初一知道的許嵩,而後就一直聽了下來,不知不覺已經大一了,突然感受時間過得太快了,,,,那年的我喜歡和她一塊兒坐在操場的臺階上聽着這首歌,如今的她還好麼? 2015-07-05 21:33:54 lyc鞦韆墜:記得初二時在考場拼命背書爲接下來的考試,聽到別人在放《清明雨上》,激動了一下,隨後又很失落。當時那麼喜歡的歌手別人也在聽着,像一杯好酒被別人偷喝了一半,爲了騙本身兌上水,卻失了原來的味道。再者,總以爲,這樣的歌只適合一我的靜靜聽,在那麼寬敞的地方放,總以爲被破壞了。 2014-12-05 17:09:40 個人名字十二字不信你數數:你總說畢業遙遙無期 轉眼卻各奔東西................. 2016-04-04 22:28:55 媽媽說張澤華會是建築大師:媽,我來看你了。麥苗已經長得很高是你喜歡的但願綠。跟着爸爸後面走向你小時候一塊兒旅遊的模樣。那年在北京廟會我推着輪椅你新奇少數民族的各類風俗不肯再待在醫院等死。如今對全部糯米類的食物迷之愛戀即便是前段時間的青團也容易讓我想到當初餵你湯圓的時候你把黑芝麻吃掉把軟軟的湯圓皮餵給個人樣子 2017-03-07 14:46:59 此乃一:十年了,想當年在安醫上學的時候,你也沒和我上下鋪,可是也睡在我對面的下鋪,有時候你在寢室哼着沒有沒有名字的歌曲,你們都在想着你之後能夠去唱歌,有時候寢室去逍遙津玩,你也忙着去寫歌,結果這麼多年過去了,你果真去唱歌了,而我也循序漸進的成爲了一名醫生,也許這就是人各有志吧,523。 2014-12-06 22:17:22 煮壺時光品良辰:傳唱許嵩歌,誰知歌裏愁? 2016-02-06 18:26:49 杜大官人: 「庭有枇杷樹,吾妻死之年所手植也,今已亭亭如蓋矣」 2015-04-04 14:10:05 女俠七七可能不是流氓:又是一年清明。如今大二。固然不會忘記初中有多瘋狂的迷戀他的音樂和他這我的。那時候聽清明雨上會腦補若是有MV就該是黑白畫面,正裝許嵩站在小雨中在墓碑上放一朵白菊。晚上作的夢就不太好了,夢裏墓碑上是個人照片……初中同窗應該記得吧[大哭] 2014-11-10 18:44:22 蛋撻皮衣:個人許嵩許嵩許嵩。喜歡你 原本與你就無關 何必在意更多其餘的聲音[可愛] 2018-04-05 07:17:10 新長征路上的-搖滾:那年剛聽這歌的時候我奶奶外婆還健在,現在她們都已駕鶴西去,最大的遺憾是由於駐守在祖國的西南邊陲二位最疼個人老人離世時我都在執行任務,我都沒能趕會去見最後一面,送上最後一程。奶奶,外婆,又是清明節了,我再也吃不到大家作的清明果,喝不到大家採的清明茶了,大家在那邊還好嗎? 2018-04-09 15:24:03 酥酥的醬:爲什麼是清明雨上而非雨下? 雨上是有你的天堂,雨下獨留我彷徨 2019-04-05 22:28:47 vinegar醋醋:當年清明有嵩鼠給我打電話唱這首歌。轉眼已經六七年 2019-04-05 22:28:46 碰見碰見碰見1997:今年的清明節沒有下雨 天氣很好 願您也好❤️ 2019-04-05 22:28:44 詩卿不詩情:初一的回憶 2019-04-05 22:28:30 月初寒霜凍佳人:又是清明雨上
####解析json詳情 <img style="width:800px;height:450px" src="https://img2018.cnblogs.com/blog/841731/201904/841731-20190406140151392-1183551085.png" align=center /> 根據url容易看出limit是每頁的條數,offset是步長。隨便試了幾個參數,驗證猜測正確。解析requests返回的json結構時,開始第一頁的評論內容是hotComments,就都按照hotComments來解析。可是翻頁後出錯,原來後面其餘頁的是comments。估計是網易把歷史的熱門評論放到第一頁,後面的是按時間倒敘的平常評論 ####詞頻統計和中止詞 接下來對爬下來的txt文本進行詞頻統計,中文分詞用的是jieba庫,發現,和。等一類的無用詞出現的頻率也很高,因而在網上下載了一箇中止詞的txt文件,將一些沒有的常見詞過濾掉,不參與統計 <img style="width:800px;height:450px" src="https://img2018.cnblogs.com/blog/841731/201904/841731-20190406140451868-1895554332.png" align=center /> ####詞雲圖 剛開始的時候,圖片裏的中文是亂碼,可是英文能夠正常顯示。後來發現是要加上font_path='Hiragino Sans GB.ttc',否則中文字體不能正常顯示,英文字體則能夠直接支持。 <img style="width:600px;height:600px" src="https://img2018.cnblogs.com/blog/841731/201904/841731-20190406140734195-1689036786.jpg" align=center /> ####源碼以下ajax
# coding: utf-8 import requests import json import time from wordcloud import WordCloud import jieba import numpy import PIL.Image as Image import io headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36", "referer": "http://music.163.com/song?id=167882&market=baiduqk" } stop_path = "./source/stopword.txt" comment_path = "./source/coments.txt" # 獲取單頁評論,寫入文件 def get_comments(url): res = requests.post(url, headers=headers) comments_json = json.loads(res.text) if ('hotComments' in comments_json): comments = comments_json['hotComments'] else: comments = comments_json['comments'] # w是寫,a是追加 with open(comment_path, 'a') as f: for each in comments: comment_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(each['time'] / 1000)) f.write(comment_time + ' ' + each['user']['nickname'] + ':' + each['content'] + '\n') # 請求格式 # host = "http://music.163.com/api/v1/resource/comments/R_SO_4_167882?limit=20&offset=0"; def get_all_comments(): # 歌曲id id = "167882" page = 150 base_url = "http://music.163.com/api/v1/resource/comments/R_SO_4_" + id + "?limit=20&offset=" for p in range(page): offset = p * 20 url = base_url + str(offset) get_comments(url) print("page " + str(p + 1) + " finish") # 統計詞頻 def word_count(): with io.open(comment_path, encoding="utf-8") as file: file = file.read() stopwords = [line.strip() for line in open(stop_path).readlines()] words = jieba.lcut(file) counts = {} for word in words: if word not in stopwords: # 不統計字數爲一的詞 if len(word) == 1: continue else: counts[word] = counts.get(word, 0) + 1 items = list(counts.items()) items.sort(key=lambda x: x[1], reverse=True) for i in range(50): word, count = items[i] print ("{:<10}{:>7}".format(word, count)) # 生成詞雲圖 def word_cloud(): with io.open(comment_path, encoding="utf-8") as file: file = file.read() text = ''.join(jieba.cut(file)) mask_pic = numpy.array(Image.open("./source/1.jpg")) stopwords = open(stop_path).read() # 3.設置詞雲的背景顏色、寬高、字數 wordcloud = WordCloud( font_path='Hiragino Sans GB.ttc', mask=mask_pic, stopwords=stopwords, background_color="white", width=1200, height=600, max_words=500 ).generate(text) file_name = "./pic/" + time.strftime("%Y%m%d%H%M%S", time.localtime()) + ".jpg" wordcloud.to_file(file_name) print("save pic finish:" + time.strftime("%Y%m%d%H%M%S", time.localtime()) + ".jpg") image = wordcloud.to_image() image.show() def main(): # 獲取前150頁評論 get_all_comments() # 生成詞雲圖 word_cloud() # 統計詞頻 word_count() if __name__ == "__main__": main()