【原創(chuàng)】python詞云分析陳粒和趙雷

未經(jīng)同意禁止轉(zhuǎn)載,否則通過(guò)維權(quán)騎士追究

【完整源代碼請(qǐng)點(diǎn)擊 此處 留言以獲取,可以順便給顆Star??】

記錄一個(gè)練習(xí)小項(xiàng)目,訓(xùn)練一下python分析技能。用到的知識(shí)有“爬蟲(chóng)”、“jieba分詞”、“wordcloud詞云”、“Tableau可視化”

準(zhǔn)備環(huán)境

spyder

直接使用anaconda中的spyder IDE,畢竟anaconda管理各種組件、包非常方便

python

python版本為3.6.4,之前參考網(wǎng)上不少資料,很多代碼是用python2寫的,比如unicode在python3中已經(jīng)沒(méi)有了
但有些博文中的讀取txt文件部分,仍用的python2方法,且不注明環(huán)境。千古文章一大抄

jieba

jieba庫(kù)沒(méi)有被anaconda收錄,所以需要自己去下載安裝,是zip格式
直接解壓到D:\Anaconda\pkgs 目錄下,打開(kāi) Anaconda Prompt并cd進(jìn)入jieba解壓目錄,執(zhí)行python setup.py install

wordcloud

這個(gè)地方遇到不少問(wèn)題,因?yàn)槲覜](méi)安裝vs,不具有vc編譯環(huán)境,所以直接從github上下載wordcloud的壓縮包執(zhí)行python setup.py install直接報(bào)錯(cuò)了!
去網(wǎng)上查了下資料,發(fā)現(xiàn)是缺少一個(gè)vc-build-tool下載安裝需要4G左右(ps:坑爹?。?br> 后來(lái)在wordcloud的github主頁(yè)上找到了安裝whl文件(已經(jīng)被編譯過(guò))的替代方法

whl

whl格式本質(zhì)上是一個(gè)壓縮包,里面包含了py文件,以及經(jīng)過(guò)編譯的pyd文件。使得可以在不具備編譯環(huán)境的情況下,選擇合適自己的python環(huán)境進(jìn)行安裝。
安裝方法很簡(jiǎn)單,進(jìn)入命令行輸入
pip install xxxx.whl
或者如果是升級(jí)
pip install -U xxxx.whl

流程概述

  • 爬取歌詞,保存為txt文件
  • bat命令,合并同一個(gè)歌手所有txt文件(建立一個(gè)bat文件,內(nèi)容為 type *.txt >> all.txt,編碼和源文件相同)
  • 對(duì)合并的歌詞txt文件,調(diào)用jieba進(jìn)行分詞
  • 針對(duì)分詞的結(jié)果繪制詞云圖
  • 統(tǒng)計(jì)分詞結(jié)果,Tableau進(jìn)行結(jié)果展示分析

爬取歌詞

在download_lyric(1007170)這句中改歌手ID1007170即可爬取其他歌手的全部歌曲歌詞
歌詞源來(lái)自網(wǎng)易云音樂(lè);從歌手主頁(yè)上爬取網(wǎng)易收錄的該歌手所有歌曲




def get_html(url):
    headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.79 Safari/537.36'}
    try:
        response = requests.get(url, headers=headers)
        html = response.content
        return html
    except:
        print('request error')
        pass

def download_by_music_id(music_id):
    lrc_url = 'http://music.163.com/api/song/lyric?'+'id='+str(music_id) + '&lv=1&kv=1&tv=-1'
    r = requests.get(lrc_url)
    json_obj = r.text
    j = json.loads(json_obj)
    try:
        lrc = j['lrc']['lyric']
        pat = re.compile(r'\[.*\]')
        lrc = re.sub(pat, "",lrc)
        lrc = lrc.strip()
        return lrc
    except:
        pass

def get_music_ids_by_musician_id(singer_id):
    singer_url = 'http://music.163.com/artist?id={}'.format(singer_id)
    r = get_html(singer_url)
    soupObj = BeautifulSoup(r,'lxml')
    song_ids = soupObj.find('textarea').text
    jobj = json.loads(song_ids)
    ids = {}
    for item in jobj:
        print(item['id'])
        ids[item['name']] = item['id']
    return ids

def download_lyric(uid):
    try:
        os.mkdir(str(uid))
    except:
        pass

    os.chdir(str(uid))
    music_ids = get_music_ids_by_musician_id(uid)
    for key in music_ids:
        text = download_by_music_id(music_ids[key])        
        file = open(key+'.txt', 'a', encoding='ansi')  #創(chuàng)建的文本以ansi編碼
        file.write(key+'\n')
        file.write(str(text))
        file.close()

if __name__ == '__main__':
    download_lyric(1007170)     #只需要在這里更改網(wǎng)易云音樂(lè)web網(wǎng)站上,歌手主頁(yè)url后的ID即可,比如陳粒是1007170

jieba分詞

參考

添加自定義詞典(usr_dict)

  • 開(kāi)發(fā)者可以指定自己自定義的詞典,以便包含 jieba 詞庫(kù)里沒(méi)有的詞。雖然 jieba 有新詞識(shí)別能力,但是自行添加新詞可以保證更高的正確率
  • 用法: jieba.load_userdict(file_name) # file_name 為文件類對(duì)象或自定義詞典的路徑
  • 詞典格式和 dict.txt 一樣,一個(gè)詞占一行;每一行分三部分:詞語(yǔ)、詞頻(可省略)、詞性(可省略),用空格隔開(kāi),順序不可顛倒。file_name 若為路徑或二進(jìn)制方式打開(kāi)的文件,則文件必須為 UTF-8 編碼。
  • 詞頻省略時(shí)使用自動(dòng)計(jì)算的能保證分出該詞的詞頻。

添加忽略詞語(yǔ)(stop_word)

  • 主要思想是分詞過(guò)后,遍歷一下停用詞表,去掉停用詞。
#!/usr/bin/env python3
#遇到的編碼字符流問(wèn)題參考了如下博客的解決方案
#https://blog.csdn.net/zhangyunfei_happy/article/details/47169939
jieba.load_userdict('usr_dict.txt')
def stopwordslist(filepath):
    stopwords = [line.strip() for line in open(filepath, 'r',encoding='utf-8').readlines()]
    return stopwords

# 對(duì)句子進(jìn)行分詞
def seg_sentence(sentence):
    sentence_seged = jieba.cut(sentence.strip())
    stopwords = stopwordslist('stop_word.txt')  # 這里加載停用詞的路徑
    outstr = ''
    for word in sentence_seged:
        if word not in stopwords:
            if word != '\t':
                outstr += word
                outstr += " "
    return outstr

if __name__ == '__main__':
    
   
    inputs = open('all.txt', 'r',encoding='ansi')  #源文件是'utf-8'編碼,
    outputs = open('all_outputs.txt', 'w',encoding='utf-8')  #保存為utf8編碼
    for line in inputs:
        line_seg = seg_sentence(line)  # 這里的返回值是字符串
        #注意有些符號(hào)是中英文兩種格式,所以都要包含進(jìn)去
        line_seg = re.sub("[A-Za-z0-9\[\`\~\!\@\#\$\^\&\*\(\)\=\|\{\}\'\:\;\'\,\[\]\.\<\>\/\?\~\!\@\#\\\&\*\%\:\(\)]", "", line_seg)
        outputs.write(line_seg)
        outputs.write('\n')
    outputs.close()
    inputs.close()

wordcloud詞云

選擇背景圖片,顏色最好對(duì)比分明,不然生成的詞圖,輪廓不明顯

# coding: utf-8
import re
import jieba
from scipy.misc import imread  # 這是一個(gè)處理圖像的函數(shù)
from wordcloud import WordCloud, STOPWORDS, ImageColorGenerator

import matplotlib.pyplot as plt
#選擇背景圖片,顏色最好對(duì)比分明,不然生成的詞圖,輪廓不明顯
back_color = imread('chenli.jpg')  # 解析該圖片

# WordCloud各含義參數(shù)請(qǐng)點(diǎn)擊 wordcloud參數(shù)
wc = WordCloud(background_color='white',  # 背景顏色
               max_words=1000,  # 最大詞數(shù)
               mask=back_color,  # 以該參數(shù)值作圖繪制詞云,這個(gè)參數(shù)不為空時(shí),width和height會(huì)被忽略
               max_font_size=100,  # 顯示字體的最大值
               stopwords=STOPWORDS.add(' '),  # 使用內(nèi)置的屏蔽詞,再添加'茍利國(guó)'
               font_path="C:/Windows/Fonts/msyhbd.ttc",  # 顯示中文,從屬性里復(fù)制字體名稱,不能直接看windows顯示的字體名
               random_state=42,  # 為每個(gè)詞返回一個(gè)PIL顏色
               # width=1000,  # 圖片的寬
               # height=860  #圖片的長(zhǎng)
               )


# 添加自己的詞庫(kù)分詞,比如添加'陳粒啊'到j(luò)ieba詞庫(kù)后,當(dāng)你處理的文本中含有“陳粒啊”這個(gè)詞,
# 就會(huì)直接將'陳粒啊'當(dāng)作一個(gè)詞,而不會(huì)得到'陳粒'或'粒啊'這樣的詞
jieba.add_word('陳粒啊')

# 打開(kāi)詞源的文本文件,加read以字符串的形式
txt = open('all_outputs.txt','r',encoding='UTF-8').read()
# 去除文本中的英文,特殊符號(hào)等,只保留中文
txt = re.sub("[A-Za-z0-9\[\`\~\!\@\#\$\^\&\*\(\)\=\|\{\}\'\:\;\'\,\[\]\.\<\>\/\?\~\!\@\#\\\&\*\%]", "", txt)

# 該函數(shù)的作用就是把屏蔽詞去掉,使用這個(gè)函數(shù)就不用在WordCloud參數(shù)中添加stopwords參數(shù)了
# 把你需要屏蔽的詞全部放入一個(gè)stopwords文本文件里即可
def stop_words(texts):
    words_list = []
    word_generator = jieba.cut(texts, cut_all=False)  # 返回的是一個(gè)迭代器
    with open('stop_word.txt','r',encoding='UTF-8') as f:
        str_text = f.read()
        #print(str_text)  #如果不知道解碼是否正確,可print一下,看輸出的中文是否亂碼
        f.close()  # stopwords文本中詞的格式是'一詞一行'
    for word in word_generator:
        if word.strip() not in str_text:
            words_list.append(word)
    return ' '.join(words_list)  # 注意是空格

# 分詞統(tǒng)計(jì)
把分詞后的結(jié)果按`詞語(yǔ)+頻數(shù)`的格式保存為txt和excel文件,方便Tableau處理加工
``` python
# -*- coding:utf-8 -*-
import sys, jieba, jieba.analyse, xlwt
if __name__ == "__main__":
    wbk = xlwt.Workbook(encoding='ascii')
    sheet = wbk.add_sheet("wordCount")  # Excel單元格名字
    word_lst = []
    key_list = []
    for line in open('all_outputs.txt', 'rb'):  # 1.txt是需要分詞統(tǒng)計(jì)的文檔
        item = line.strip('\n\r'.encode('utf-8')).split('\t'.encode('utf-8'))  # 制表格切分
       
        tags = jieba.analyse.extract_tags(item[0])  # jieba分詞
        for t in tags:
            word_lst.append(t)
    word_dict = {}
    with open("wordCount.txt", 'bw') as wf2:  # 打開(kāi)文件
        for item in word_lst:
            if item not in word_dict:  # 統(tǒng)計(jì)數(shù)量
                word_dict[item] = 1
            else:
                word_dict[item] += 1
        orderList = list(word_dict.values())
        orderList.sort(reverse=True)
        # print orderList
        for i in range(len(orderList)):
            for key in word_dict:
                if word_dict[key] == orderList[i]:
                    wf2.write((key + ' ' + str(word_dict[key])).encode('utf-8'))  # 寫入txt文檔
                    wf2.write('\n'.encode('utf-8'))  # 寫入txt文檔
                    key_list.append(key)
                    word_dict[key] = 0

    for i in range(len(key_list)): #為了便于tableau限量統(tǒng)計(jì),可改為 for i in range(200),限定200個(gè)詞
        sheet.write(i, 1, label=orderList[i])
        sheet.write(i, 0, label=key_list[i])
    wbk.save('wordCount.xls')  # 保存為 wordCount.xls文件

結(jié)果展示

獲取的歌詞文件

進(jìn)行分詞

分詞統(tǒng)計(jì)

詞云

陳粒.png

陳粒的詞云


趙雷.png

趙雷的詞云

Tableau可視化

趙雷統(tǒng)計(jì).png

趙雷的歌詞頻數(shù)統(tǒng)計(jì)


陳粒統(tǒng)計(jì).png

陳粒的歌詞頻數(shù)統(tǒng)計(jì)


對(duì)比.png

陳、趙歌詞相似度統(tǒng)計(jì)

遇到的問(wèn)題

wordcloud命名問(wèn)題

File "E:\CZK\工作\數(shù)據(jù)分析\我的練習(xí)項(xiàng)目\詞云項(xiàng)目\wordcloud.py", line 5, in <module>
    from wordcloud import WordCloud, STOPWORDS, ImageColorGenerator
ImportError: cannot import name 'WordCloud'

解決辦法

從wordcloud作者的github及stackoverflow上均找到了答案,不得不說(shuō)google搜索大法好!
改py文件的名字,就是不要以“wordcloud”命名你的py文件

包未編譯問(wèn)題

  File "E:/CZK/工作/數(shù)據(jù)分析/我的練習(xí)項(xiàng)目/詞云項(xiàng)目/get_wordcloud.py", line 4, in <module>
    from wordcloud import WordCloud, STOPWORDS, ImageColorGenerator
ModuleNotFoundError: No module named 'wordcloud'

解決辦法

下載whl文件,http://www.lfd.uci.edu/~gohlke/pythonlibs/#wordcloud
然后 pip install <whl文件名>

編碼和讀取文件

AttributeError: '_io.TextIOWrapper' object has no attribute 'decode' 

解決辦法

jieba.cut第一個(gè)參數(shù)為str不是file,所以open文件時(shí)需要有.read()
另外讀取,存儲(chǔ)文本時(shí),要注意源文件編碼,encoding=xxxx,具體可閱讀源代碼

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • jieba分詞,學(xué)習(xí),為了全面了解該模塊,,預(yù)設(shè)學(xué)習(xí)路線:官方文檔——優(yōu)秀博客文章——實(shí)踐學(xué)習(xí) 官方文檔部分 (文...
    竹林徒兒閱讀 4,471評(píng)論 1 12
  • 目錄 方法概述 分詞——Jieba 詞頻分析與詞云 方法概述 1、使用歌曲《山僧》的歌詞片段為素材,進(jìn)行分析。 經(jīng)...
    Hana_5f9b閱讀 1,636評(píng)論 0 1
  • 每天晚上睡覺(jué)之前,我都會(huì)拿著kindle看一小會(huì)書(shū)。像民國(guó)的老毒棍抽大煙一樣,斜躺著身體靠在床上吸食精神鴉片...
    melongod1閱讀 11,709評(píng)論 7 32
  • 俗話說(shuō)千金難買老來(lái)瘦,我的外公中等身材,體型就是偏瘦的那一種。他很愛(ài)干凈,衣服被子自己疊得整整齊齊。我二表哥十幾歲...
    尹老三閱讀 389評(píng)論 0 6
  • 在做決定的時(shí)候,不妨適當(dāng)?shù)厥湛s選擇范圍,別挑花了眼;當(dāng)工作生活遇到瓶頸的時(shí)候,拓展體驗(yàn)邊界比執(zhí)著于問(wèn)題本身更有效;...
    要學(xué)說(shuō)話的NJ閱讀 196評(píng)論 0 0

友情鏈接更多精彩內(nèi)容