參考這篇文章:python爬取歌詞并生成詞云圖 - qq_39317214的博客 - CSDN博客
注:目前爬取到的歌詞是歌手的TOP50首歌克饶,如果要抓全部的酝蜒,還需要改進(jìn)
已完成:爬取歌詞--》詞頻分析--》畫詞云
未來需要加上:
不以文本文件的形式儲(chǔ)存,而是存到數(shù)據(jù)庫(kù)里讀取來操作;
不止TOP50矾湃;
同時(shí)抓取所屬專輯信息等亡脑,之后可按專輯、年份來看意象洲尊、情感極性的變化远豺,≈專輯主題風(fēng)格奈偏;
對(duì)爬取到的歌詞預(yù)過濾坞嘀,去除音樂制作人、樂手信息惊来;-----done丽涩,190207
判斷是否是Live歌曲,以免重復(fù)計(jì)算裁蚁;
其中主要遇到過的問題有:
1矢渊、編碼解碼
在file.write(str(text))時(shí)報(bào)錯(cuò):
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)
原因是Python自然調(diào)用ascii編碼解碼程序去處理字符流,當(dāng)字符流不屬于ascii范圍內(nèi)枉证,就會(huì)拋出異常(ordinal not in range(128))矮男。所以解決方法就是修改默認(rèn)編碼,需要注意的是需要先調(diào)用reload方法室谚。
進(jìn)一步解釋可參考UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128) - 小樓 - 博客園
解決辦法:
在開頭加上:
import sys
reload(sys)
sys.setdefaultencoding( "utf-8" )
2毡鉴、歌名中包含了句點(diǎn)"?"等非法字符,導(dǎo)致以歌名作為文件名來創(chuàng)建文本文件key.txt時(shí)出現(xiàn)問題無法成功創(chuàng)建:
比如張懸有一首歌是“So?!...”秒赤,在運(yùn)行時(shí)就會(huì)報(bào)錯(cuò):
? ? file = open(key+'.txt', 'a')
IOError: [Errno 22] invalid mode ('a') or filename: u'So?!....txt'
此時(shí)要將歌名中的這些非法字符去掉猪瞬,比較好的方法是替換為下劃線_ ,參考Python中過濾Windows文件名中的非法字符 - Zerokas的博客 - CSDN博客? 寫了以下替換函數(shù):
#函數(shù):當(dāng)歌名中包含'?'等非法字符時(shí)無法創(chuàng)建文件為.txt入篮,對(duì)這類歌名將非法字符替換成下劃線_
def correct_filename(song_name):
? ? ? ? pattern = r'[\\/:*?"<>|\r\n]+'
? ? ? ? new_song_name = re.sub(pattern, "_", song_name)
? ? ? ? return new_song_name
2.1陈瘦、unicode字符串轉(zhuǎn)換成string字符串(文件名可以用.結(jié)尾,所以不改也沒事)
這里仍然涉及到編碼問題潮售,代碼里一開始爬取到的歌名(key)是Unicode字符串痊项,在判斷是否是以“.”句點(diǎn)結(jié)尾時(shí)需要轉(zhuǎn)換成string字符串锅风,因此用到了key.encode('utf-8')。(因?yàn)槲业拇a文件是用utf-8編碼的)
參考:Python2.X如何將Unicode中文字符串轉(zhuǎn)換成 string字符串 - qiao1234 - 博客園
2.2鞍泉、去停用詞時(shí)的轉(zhuǎn)碼
但是在去停用詞時(shí)又遇到了編碼的問題(所以應(yīng)該換用py3.x啊這個(gè)bug真的太難受了6羧酢):
UnicodeWarning: Unicode equal comparison failed to convert both arguments to Unicode - interpreting them as being unequal
if word not in stopwords:
因?yàn)槲乙婚_始導(dǎo)入停用詞的代碼是:
def stopwordslist(filepath):
? ? stopwords = [line.strip() for line in open(filepath, 'r').readlines()]
? ? return stopwords
只要在這一步將詞轉(zhuǎn)換成unicde編碼就可以進(jìn)行之后的判斷詞是否在停用詞表中了:
? ? stopwords = [line.strip().decode("gbk") for line in open(filepath, 'r').readlines()]
3、制作詞云過程中會(huì)遇到的小問題
3.1塞弊、字體
一開始的結(jié)果是這樣的:
還以為是編碼的問題沒搞定造成的漱逸,但是看了下中間過程中生成的字典,已經(jīng)是正確的了游沿,所以只有另一個(gè)可能:字體饰抒。
由于歌詞大部分是中文,因此要選擇支持中文的字體诀黍,比如當(dāng)我換成另一個(gè)支持中文的字體后袋坑,生成的圖片中的字就正常了:
但是馬上又有了2個(gè)新的問題:詞的分布不是按照我選用的圖片來的(我選的是一張人像照,而圖片里詞布滿了整個(gè)畫布)眯勾,以及枣宫,詞云中有大量類似“編曲”“作詞”“錄音室”這種非真正歌詞內(nèi)容的詞,反而處在最高頻率列表上吃环,所以……并不是網(wǎng)上摘一段代碼就可以完事了啊(╯‵□′)╯︵┻━┻
3.2也颤、在分詞前先剔除歌詞中音樂制作信息的內(nèi)容
觀察之前得到的詞云結(jié)果,可以發(fā)現(xiàn)有相當(dāng)多的音樂制作人信息分布在高頻詞頻表上郁轻,如何將這一部分詞剔除掉呢翅娶?這里有兩個(gè)方法:
方法1、在去停用詞后好唯,針對(duì)抓取到的歌詞特性竭沫,再過濾一遍分詞文本
通過觀察爬取到的歌詞,新生成了一個(gè)歌詞過濾文本骑篙,對(duì)去停用詞后的分詞文本進(jìn)行過濾蜕提,得到的詞云就干凈了很多,能夠展現(xiàn)出重點(diǎn)了:
但是這需要不時(shí)更新這個(gè)歌詞過濾文本靶端,加入更多的詞曲作者谎势、編曲者、音樂人等人的名字躲查,需要不斷豐富它浅。
方法2、在去停用詞前就對(duì)爬取到的歌詞做一判斷镣煮,剔除音樂制作信息的部分姐霍,僅保留純歌詞部分
可以發(fā)現(xiàn),爬取到的歌詞前幾行是音樂制作人 的信息,格式為“xxx:xxx”镊折,可以從冒號(hào)來判斷胯府,剔除一行歌詞中包含中文或英文冒號(hào)的部分,之后再進(jìn)行分詞恨胚、去停用詞骂因。這會(huì)產(chǎn)生一個(gè)新的問題,即真正歌詞中包含冒號(hào)的內(nèi)容也會(huì)被剔除赃泡,考慮到這部分歌詞存在的概率很小寒波,即使存在,對(duì)詞頻表的結(jié)果影響也很小升熊,因此暫時(shí)忽略不計(jì)俄烁。附上這一方法的代碼:
def filter_producers(lyrics):#過濾歌詞中制作人信息
? ? ? ? lyrics_filter_producers = ''
? ? ? ? for line in lyrics:
? ? ? ? ? ? ? ? if (line.find(':') != -1) | (line.find(':') != -1):#查找“歌詞”中包含中英文冒號(hào)的語(yǔ)句,string.find()返回-1表示找不到
? ? ? ? ? ? ? ? ? ? ? ? pass
? ? ? ? ? ? ? ? else:
? ? ? ? ? ? ? ? ? ? ? ? lyrics_filter_producers += line
? ? ? ? ? ? ? ? ? ? ? ? lyrics_filter_producers += '\n'
? ? ? ? return lyrics_filter_producers
3.3级野、讓詞云按照想要的圖片來生成
詞云沒有按照我想要的圖片的輪廓來生成的原因页屠,是我采用的圖片背景太過復(fù)雜、有別的顏色蓖柔,所以wordcloud沒有辦法判斷辰企,參考生成詞云之python中WordCloud包的用法 - 飛翔射手座 - CSDN博客的方法,選取背景是全白的圖片况鸣,或者我們對(duì)圖片做一些改動(dòng)牢贸,讓它的背景變成全白:
mask : nd-array or None (default=None) //如果參數(shù)為空,則使用二維遮罩繪制詞云懒闷。如果 mask 非空十减,設(shè)置的寬高值將被忽略,遮罩形狀被 mask 取代愤估。除全白(#FFFFFF)的部分將不會(huì)繪制,其余部分會(huì)用于繪制詞云速址。如:bg_pic = imread('讀取一張圖片.png')玩焰,背景圖片的畫布一定要設(shè)置為白色(#FFFFFF),然后顯示的形狀為不是白色的其他顏色芍锚∥粼埃可以用ps工具將自己要顯示的形狀復(fù)制到一個(gè)純白色的畫布上再保存,就ok了并炮。
為了方便默刚,我直接用了PPT里的“刪除背景”的功能(在PPT中,怎么刪除圖片的背景(摳圖)_百度經(jīng)驗(yàn))逃魄,將圖片處理成全白后生成了田馥甄的TOP50歌曲的歌詞詞云:
簡(jiǎn)單概括一下荤西,田馥甄的歌曲主要表達(dá)的就是:“就算沒有人陪,就算自己很寂寞,也要擁抱眼淚邪锌,遺忘所有傷勉躺,謝謝這個(gè)世界,相信自己還是可以有愛和快樂的”觅丰,嗯真的是很倔強(qiáng)的歌手呢:)