1. 程式人生 > >python資料探勘分析微信朋友圈

python資料探勘分析微信朋友圈

參考https://blog.csdn.net/qinyuanpei/article/details/79360703,基於python3.6實現微信朋友圈性別、地區、個性簽名、頭像四個維度的分析。

我的GitHub專案地址https://github.com/sanciyuan/wechat_analysis_itchat

1、準備工作

1.1 環境要求

  • WIN10
  • python3.6
  • pycharm編譯器

1.2 第三方庫要求

  • itchat:itchat是一個開源的微信個人號介面
  • jieba:結巴分詞的 Python 版本,對文字資訊進行分詞處理。 
  • matplotlib: Python 中圖表繪製模組,在本文中用以繪製柱形圖和餅圖 
  • snownlp:一個 Python 中的中文分詞模組,在本文中用以對文字資訊進行情感判斷。 
  • PIL: Python 中的影象處理模組,在本文中用以對圖片進行處理。 
  • numpy: Python中 的數值計算模組,在本文中配合 wordcloud 模組使用。 
  • wordcloud: Python 中的詞雲模組,在本文中用以繪製詞雲圖片。 
  • TencentYoutuyun:騰訊優圖提供的 Python 版本 SDK ,在本文中用以識別人臉及提取圖片標籤資訊。 

安裝問題①:

上述幾個第三方庫均可通過pip install方式安裝,除了TencentYoutuyun

通過普通的pip方法無法實現安裝,會報錯

pip install TencentYoutuyun

解決方法①:

先去github下載官方sdk的zip壓縮包至某目錄下,如E:\Project\test\Python_sdk-master.zip

https://github.com/Tencent-YouTu/Python_sdk

開啟命令列,定位到下載目錄下,再進行pip安裝,至安裝成功

e:
cd Project\test
pip install Python_sdk-master.zip

安裝問題②:

PIL目前只支援python2.x版本,不支援python3.x。

解決方法②:

Pillow是PIL的一個派生分支,但如今已經發展成為比PIL本身更具活力的影象處理庫。

Pillow的Github主頁:https://github.com/python-pillow/Pillow
Pillow的文件(對應版本v3.0.0):https://pillow.readthedocs.org/en/latest/handbook/index.html
Pillow的文件中文翻譯(對應版本v2.4.0):http://pillow-cn.readthedocs.org/en/latest/

Python 3.x 安裝Pillow

給Python安裝Pillow非常簡單,使用pip或easy_install只要一行程式碼即可。

在命令列使用PIP安裝:

pip install Pillow

或在命令列使用easy_install安裝: 

easy_install Pillow

安裝完成後,使用from PIL import Image就引用使用庫了。比如:
 

from PIL import Image
im = Image.open("bride.jpg")
im.rotate(45).show()

2、好友性別

獲取好友性別資訊,統計男、女、未知的數量,計算比例並製作餅圖視覺化。

def analyseSex(firends):
    # 將friends中的Sex資訊抽取出來,map返回的是迭代器,轉化為list格式
    sexs = list(map(lambda x:x['Sex'],friends[1:]))
    # item返回(鍵,值)元組,第一維為鍵,第二維為值,即個數
    # 取性別個數變為列表
    counts = Counter(sexs).items()
    counts = sorted(counts, key=lambda x:x[0], reverse=False)
    counts = list(map(lambda x:x[1],counts))

    labels = ['Unknow','Male','Female']
    colors = ['red','yellowgreen','lightskyblue']
    plt.figure(figsize=(8,5), dpi=80)
    plt.axes(aspect=1) 
    plt.pie(counts, 
            labels=labels, 
            colors=colors, 
            labeldistance = 1.1, 
            autopct = '%3.1f%%',
            shadow = False, 
            startangle = 90, 
            pctdistance = 0.6 
    )
    plt.legend(loc='upper right',)
    plt.title(u'%s的微信好友性別組成' % friends[0]['NickName'])
    plt.savefig("analyseSex.jpg")
    plt.show()

3、好友地區

獲取好友的地區資訊,儲存至本地'location.csv',再統計各地區的好友數量存至'location_analysis.xls’。

def analyseLocation(friends):
    freqs = {}
    headers = ['NickName','Province','City']
    with open('location.csv','w',encoding='utf-8',newline='',) as csvFile:
        # DictWriter以字典的形式寫入內容
        # 設定寫入格式
        writer = csv.DictWriter(csvFile, headers)
        #  writeheader()實現新增檔案頭(資料名)
        writer.writeheader()
        for friend in friends[1:]:
            row = {}
            row['NickName'] = friend['NickName']
            row['Province'] = friend['Province']
            row['City'] = friend['City']
            # 統計城市數目
            if(friend['Province']!=None):
                if(friend['Province'] not in freqs):
                   freqs[friend['Province']] = 1
                else:
                   freqs[friend['Province']] += 1
            writer.writerow(row)
    print(freqs)
    print(type(freqs))
    print(len(freqs))

    key_list = list(freqs.keys())
    value_list = list(freqs.values())
    book = xlwt.Workbook(encoding='utf-8')
    sheet = book.add_sheet('sheet1')
    sheet.write(0, 0, 'Province')  # 其中的'0-行, 0-列'指定表中的單元
    sheet.write(0, 1, 'Num')
    for i in range(len(freqs)):
        sheet.write(i+1, 0, key_list[i])
        sheet.write(i+1, 1, value_list[i])

    book.save('location_analysis.xls')

使用BDP報表工具https://me.bdp.cn/home.html分析地區資訊

點選上方“資料來源” ,新增資料“excel”,上傳'location_analysis.xls'——新建圖表——普通圖表、儀表盤示例、微信運營分析——維度:province,數值:num——右側,圖表型別:地圖,最後生成下圖。

4、好友頭像

呼叫騰訊優圖的人臉識別介面DetectFace和圖片標籤識別分類介面imagetag,再生成使用人臉頭像的餅圖和頭像標籤的詞雲。

- 介面
`DetectFace(self, image_path, mode = 0, data_type = 0)`
- 引數
	- `image_path` 待檢測的圖片路徑
	- `mode` 是否大臉模式,預設非大臉模式
    - `data_type` 用於表示image_path是圖片還是url, 0代表圖片,1代表url

- 介面
`imagetag(self, image_path, data_type = 0, seq = '')`
- 引數
    - `image_path` 標識圖片資訊
    - `data_type` 用於表示image_path是圖片還是url, 0代表圖片,1代表url

 

def analyseHeadImage(frineds):
    # Init Path
    basePath = os.path.abspath('.')
    baseFolder = basePath + '\\HeadImages\\'
    if not os.path.exists(baseFolder) :
    # if(os.path.exists(baseFolder) == False):
        os.makedirs(baseFolder)

    # Analyse Images
    faceApi = FaceAPI()
    use_face = 0
    not_use_face = 0
    image_tags = ''
    for index in range(1,len(friends)):
        friend = friends[index]
        # Save HeadImages
        imgFile = baseFolder + '\\Image%s.jpg' % str(index)
        imgData = itchat.get_head_img(userName = friend['UserName'])
        if not os.path.exists(imgFile):
        # if(os.path.exists(imgFile) == False):
            with open(imgFile,'wb') as file:
                file.write(imgData)

        # Detect Faces
        time.sleep(1)
        result = faceApi.detectFace(imgFile)
        if result == True:
            use_face += 1
        else:
            not_use_face += 1 

        # Extract Tags
        result = faceApi.extractTags(imgFile)
        image_tags += ','.join(list(map(lambda x:x['tag_name'],result)))
    
    labels = [u'使用人臉頭像',u'不使用人臉頭像']
    counts = [use_face,not_use_face]
    colors = ['red','yellowgreen','lightskyblue']
    plt.figure(figsize=(8,5), dpi=80)
    plt.axes(aspect=1) 
    plt.pie(counts, #性別統計結果
            labels=labels, #性別展示標籤
            colors=colors, #餅圖區域配色
            labeldistance = 1.1, #標籤距離圓點距離
            autopct = '%3.1f%%', #餅圖區域文字格式
            shadow = False, #餅圖是否顯示陰影
            startangle = 90, #餅圖起始角度
            pctdistance = 0.6 #餅圖區域文字距離圓點距離
    )
    plt.legend(loc='upper right',)
    plt.title(u'%s的微信好友使用人臉頭像情況' % friends[0]['NickName'])
    plt.savefig("analyseHeadImage.jpg")
    plt.show() 

    image_tags = image_tags.encode('iso8859-1').decode('utf-8')
    back_coloring = np.array(Image.open('face.jpg'))
    wordcloud = WordCloud(
        font_path='simfang.ttf',
        background_color="white",
        max_words=1200,
        mask=back_coloring, 
        max_font_size=85,
        random_state=75,
        width=800, 
        height=480, 
        margin=15
    )

    wordcloud.generate(image_tags)
    plt.imshow(wordcloud)
    plt.axis("off")
    plt.savefig("wordcloudHeadImage.jpg")
    plt.show()

  

5、好友個性簽名

先獲取好友簽名信息,再對文字做預處理,呼叫SnowNLP介面對文字做情感分析。

def analyseSignature(friends):
    signatures = ''
    emotions = []
    pattern = re.compile("1f\d.+")
    for friend in friends:
        signature = friend['Signature']
        if(signature != None):
            signature = signature.strip().replace('span', '').replace('class', '').replace('emoji', '')
            signature = re.sub(r'1f(\d.+)','',signature)
            if(len(signature)>0):
                nlp = SnowNLP(signature)
                emotions.append(nlp.sentiments)
                # 關鍵詞提取,返回5個TF/IDF權重最大的關鍵詞
                signatures += ' '.join(jieba.analyse.extract_tags(signature,5))
    with open('signatures.txt','wt',encoding='utf-8') as file:
         file.write(signatures)

    # Sinature WordCloud
    back_coloring = np.array(Image.open('flower.jpg'))
    wordcloud = WordCloud(
        font_path='simfang.ttf',
        background_color="white",
        max_words=1200,
        mask=back_coloring, 
        max_font_size=75,
        random_state=45,
        width=960, 
        height=720, 
        margin=15
    )

    wordcloud.generate(signatures)
    plt.imshow(wordcloud)
    plt.axis("off")
    plt.show()
    wordcloud.to_file('signatures.jpg')
    
    # Signature Emotional Judgment
    count_good = len(list(filter(lambda x:x>0.66,emotions)))    # 正面情感統計
    count_normal = len(list(filter(lambda x:x>=0.33 and x<=0.66,emotions))) # 中性情感統計
    count_bad = len(list(filter(lambda x:x<0.33,emotions)))     # 負面情感統計
    # 計算情感比例值
    print(count_good * 100/len(emotions))
    print(count_normal * 100/len(emotions))
    print(count_bad * 100/len(emotions))
    labels = [u'負面消極',u'中性',u'正面積極']
    values = (count_bad,count_normal,count_good)
    plt.rcParams['font.sans-serif'] = ['simHei'] 
    plt.rcParams['axes.unicode_minus'] = False
    plt.xlabel(u'情感判斷')
    plt.ylabel(u'頻數')
    plt.xticks(range(3),labels)
    plt.legend(loc='upper right',)
    plt.bar(range(3), values, color = 'rgb')
    plt.title(u'%s的微信好友簽名信息情感分析' % friends[0]['NickName'])
    plt.savefig("analyseSignatureEmotional.jpg")
    plt.show()