微信:一個提供即時通信服務的應用程序,更是一種生活方式,超過數十億的使用者,愈來愈多的人選擇使用它來溝通交流。html
不知從什麼時候起,咱們的生活離不開微信,天天睜開眼的第一件事就是打開微信,關注着朋友圈裏好友的動態,而朋友圈中或虛或實的狀態更新,彷佛都在證實本身的「有趣」,尋找那份或有或無的存在感。python
有人選擇在朋友圈記錄生活的點滴,有人選擇在朋友圈展現本身的觀點。有時咱們想去展現本身,有時又想去窺探着別人的生活,而有時又不想別人過多的瞭解本身的生活,或是屏蔽對方,或是不給對方看朋友圈,又或是不想看對方的朋友圈。json
做者本人也是微信的重度依賴者,天天的工做生活都離不開它,也會關注朋友圈裏好友的動態,我我的認爲微信朋友圈是一種文化的體現,諸如:髮圈、點贊、留言等,都能側面的反應一我的的生活、工做、心態、愛好、修養、上進心、努力程度等。api
今天就跟着我一塊兒來揭祕微信朋友圈,利用 Python+AI人工智能 進行多角度分析,一塊兒看透你的「朋友圈」。微信
咱們將使用Python抓取朋友圈數據,並對獲取到的數據進行全面分析,包含好友性別、地理位置分佈、個性簽名、備註名、好友類型等,逐一進行分析,同時還會使用人臉識別技術對好友頭像進行分析,分析到你懷疑人生。。。。。。app
整個過程分爲四步:echarts
獲取數據dom
處理數據ide
存儲數據函數
數據可視化
1、獲取數據
關於微信好友數據的獲取,能夠經過itchat庫,itchat是一個開源的微信我的號的接口,能夠實現信息收發、獲取好友列表等功能。
具體的用法和說明,在代碼中已經作了詳細的註釋。
#!/usr/bin/env python3 # -*- coding: utf-8 -*- # 導入itchat模塊,操做微信我的號的接口 import itchat # 獲取數據 def get_data(): # 掃描二維碼登錄微信,實際上就是經過網頁版微信登錄 itchat.auto_login() # 獲取全部好友信息 friends = itchat.get_friends(update=True) # 返回一個包含用戶信息字典的列表 return friends if __name__ == '__main__': print(get_data())
執行代碼時電腦屏幕會出現一個二維碼,手機微信掃描後便可完成登錄!
2、處理數據
對獲取的數據進行處理,篩選出須要的數據。
經過對返回的用戶信息進行分析,發現列表中第一個元素是用戶本身,能夠排除掉。同時咱們只取須要的字段數據,各個字段及其取值的含義已在代碼中作了說明。
# 處理數據 def parse_data(data): friends = [] for item in data[1:]: # 第一個元素是本身,排除掉 friend = { 'NickName': item['NickName'], # 暱稱 'RemarkName': item['RemarkName'], # 備註名 'Sex': item['Sex'], # 性別:1男,2女,0未設置 'Province': item['Province'], # 省份 'City': item['City'], # 城市 'Signature': item['Signature'].replace('\n', ' ').replace(',', ' '), # 個性簽名(處理簽名內容換行的狀況) 'StarFriend': item['StarFriend'], # 星標好友:1是,0否 'ContactFlag': item['ContactFlag'] # 好友類型及權限:1和3好友,259和33027不讓他看個人朋友圈,65539不看他的朋友圈,65795兩項設置全禁止 } print(friend) friends.append(friend) return friends if __name__ == '__main__': print(parse_data(get_data()))
3、存儲數據
爲了便於分析數據並進行可視化操做,這裏將數據存儲到文本文件中。
# 存儲數據,存儲到文本文件 def save_to_txt(): friends = parse_data(get_data()) for item in friends: with open('friends.txt', mode='a', encoding='utf-8') as f: f.write('%s,%s,%d,%s,%s,%s,%d,%d\n' % ( item['NickName'], item['RemarkName'], item['Sex'], item['Province'], item['City'], item['Signature'], item['StarFriend'], item['ContactFlag'])) if __name__ == '__main__': save_to_txt()
重要說明: 這裏我獲取的是本身的微信好友數據(共計950條,因工做關係,好友數比較多),考慮到我的隱私,部分信息作了處理。
4、數據可視化
這裏使用的是pyecharts,pyecharts是一個用於生成Echarts圖表的類庫,便於在Python中根據數據生成可視化的圖表。
Echarts是百度開源的一個數據可視化JS庫,主要用於數據可視化。
# 安裝pyecharts pip install pyecharts
1. 好友性別分析
代碼實現:
#!/usr/bin/env python3 # -*- coding: utf-8 -*- # 導入Pie組件,用於生成餅圖 from pyecharts import Pie # 獲取全部性別 sex = [] with open('friends.txt', mode='r', encoding='utf-8') as f: rows = f.readlines() for row in rows: sex.append(row.split(',')[2]) # print(sex) # 統計每一個性別的數量 attr = ['帥哥', '美女', '未知'] value = [sex.count('1'), sex.count('2'), sex.count('0')] pie = Pie('好友性別比例', '好友總人數:%d' % len(sex), title_pos='center') pie.add('', attr, value, radius=[30, 75], rosetype='area', is_label_show=True, is_legend_show=True, legend_top='bottom') # pie.show_config() pie.render('好友性別比例.html')
可視化結果:
好友主要爲男性,佔比70%,男女比例嚴重失衡
看到這個結果,我是有些淡淡憂桑的,微信好友總人數爲950,帥哥佔比70.42%,美女佔比24.53%,男女比例嚴重失衡,但一點也不意外,本人是一名IT工做者,平時喜歡跑步,因此工做、生活接觸到的大部分都是男性朋友,出現男女比例失衡實屬正常。
2. 好友位置分析
pyecharts v0.3.2之後,pyecharts 將再也不自帶地圖 js 文件。如用戶須要用到地圖圖表,可自行安裝對應的地圖文件包。
# 安裝地圖文件包 pip install echarts-china-provinces-pypkg # 中國省、市、縣、區地圖 pip install echarts-china-cities-pypkg pip install echarts-china-counties-pypkg pip install echarts-china-misc-pypkg pip install echarts-countries-pypkg # 全球國家地圖 pip install echarts-united-kingdom-pypkg
代碼實現:
# 導入Counter類,用於統計值出現的次數 from collections import Counter # 導入Geo組件,用於生成地理座標類圖 from pyecharts import Geo import json # 導入Bar組件,用於生成柱狀圖 from pyecharts import Bar # 數據可視化 def render(): # 獲取全部城市 cities = [] with open('friends.txt', mode='r', encoding='utf-8') as f: rows = f.readlines() for row in rows: city = row.split(',')[4] if city != '': # 去掉城市名爲空的值 cities.append(city) # 對城市數據和座標文件中的地名進行處理 handle(cities) # 統計每一個城市出現的次數 data = Counter(cities).most_common() # 使用Counter類統計出現的次數,並轉換爲元組列表 print(data) # 根據城市數據生成地理座標圖 geo = Geo('好友位置分佈', '', title_color='#fff', title_pos='center', width=1200, height=600, background_color='#404a59') attr, value = geo.cast(data) geo.add('', attr, value, visual_range=[0, 500], visual_text_color='#fff', symbol_size=15, is_visualmap=True, is_piecewise=True) geo.render('好友位置分佈.html') # 根據城市數據生成柱狀圖 data_top20 = Counter(cities).most_common(20) # 返回出現次數最多的20條 bar = Bar('好友所在城市TOP20', '', title_pos='center', width=1200, height=600) attr, value = bar.cast(data_top20) bar.add('', attr, value, is_visualmap=True, visual_text_color='#fff', is_more_utils=True, is_label_show=True) bar.render('好友所在城市TOP20.html')
出現的問題:
報錯:ValueError: No coordinate is specified for xxx(地名)
緣由:pyecharts的座標文件中沒有該地名,其實是名稱不一致致使的,如數據中地名爲'達州',而座標文件中爲'達州市'
座標文件所在路徑:項目/venv/lib/python3.6/site-packages/pyecharts/datasets/city_coordinates.json
解決:修改座標文件,在原位置下複製個一樣的,而後修改下地名
{ "南京市": [ 107.5, 31.22 ], "南京": [ 107.5, 31.22 ], }
不過因爲要修改的地名太多,上面的方法實在是麻煩,因此我定義了一個函數,用來處理地名數據找不到的問題
# 處理地名數據,解決座標文件中找不到地名的問題 def handle(cities): # print(len(cities), len(set(cities))) # 獲取座標文件中全部地名 data = None with open( '/Users/wangbo/PycharmProjects/python-spider/venv/lib/python3.6/site-packages/pyecharts/datasets/city_coordinates.json', mode='r', encoding='utf-8') as f: data = json.loads(f.read()) # 將str轉換爲json # 循環判斷處理 data_new = data.copy() # 拷貝全部地名數據 for city in set(cities): # 使用set去重 # 處理地名爲空的數據 if city == '': while city in cities: cities.remove(city) count = 0 for k in data.keys(): count += 1 if k == city: break if k.startswith(city): # 處理簡寫的地名,如 達州市 簡寫爲 達州 # print(k, city) data_new[city] = data[k] break if k.startswith(city[0:-1]) and len(city) >= 3: # 處理行政變動的地名,如縣改區 或 縣改市等 data_new[city] = data[k] break # 處理不存在的地名 if count == len(data): while city in cities: cities.remove(city) # print(len(data), len(data_new)) # 寫入覆蓋座標文件 with open( '/Users/wangbo/PycharmProjects/python-spider/venv/lib/python3.6/site-packages/pyecharts/datasets/city_coordinates.json', mode='w', encoding='utf-8') as f: f.write(json.dumps(data_new, ensure_ascii=False)) # 將json轉換爲str
可視化結果:
好友主要集中在江蘇及周邊地區
從圖中能夠發現:個人微信好友主要集中在江蘇及周邊地區,本人大學讀書時來到南京,如今工做生活也一直在南京,因此南京好友最多,爲483個;我自小在徐州長大,因此徐州好友數量也較多;同時由於喜歡跑步,結識了許多跑友,也常常會到周邊沿海城市參加各類馬拉松活動,因此好友位置主要分佈在沿海一帶。
3. 個性簽名詞雲圖
jieba是一個基於Python的分詞庫,完美支持中文分詞,功能強大
pip install jieba
Matplotlib是一個Python的2D繪圖庫,可以生成高質量的圖形,能夠快速生成繪圖、直方圖、功率譜、柱狀圖、偏差圖、散點圖等
pip install matplotlib
wordcloud是一個基於Python的詞雲生成類庫,能夠生成詞雲圖
pip install wordcloud
代碼實現:
#!/usr/bin/env python3 # -*- coding: utf-8 -*- # 導入jieba模塊,用於中文分詞 import jieba # 導入matplotlib,用於生成2D圖形 import matplotlib.pyplot as plt # 導入wordcount,用於製做詞雲圖 from wordcloud import WordCloud, STOPWORDS # 獲取全部個性簽名 signatures = [] with open('friends.txt', mode='r', encoding='utf-8') as f: rows = f.readlines() for row in rows: signature = row.split(',')[5] if signature != '': signatures.append(signature) # 設置分詞 split = jieba.cut(str(signatures), cut_all=False) # False精準模式分詞、True全模式分詞 words = ' '.join(split) # 以空格進行拼接 # print(words) # 設置屏蔽詞,去除個性簽名中的表情、特殊符號等 stopwords = STOPWORDS.copy() stopwords.add('span') stopwords.add('class') stopwords.add('emoji') stopwords.add('emoji1f334') stopwords.add('emoji1f388') stopwords.add('emoji1f33a') stopwords.add('emoji1f33c') stopwords.add('emoji1f633') # 導入背景圖 bg_image = plt.imread('bg.jpg') # 設置詞雲參數,參數分別表示:畫布寬高、背景顏色、背景圖形狀、字體、屏蔽詞、最大詞的字體大小 wc = WordCloud(width=1024, height=768, background_color='white', mask=bg_image, font_path='STKAITI.TTF', stopwords=stopwords, max_font_size=400, random_state=50) # 將分詞後數據傳入雲圖 wc.generate_from_text(words) plt.imshow(wc) # 繪製圖像 plt.axis('off') # 不顯示座標軸 # 保存結果到本地 wc.to_file('個性簽名詞雲圖.jpg')
可視化結果:
充滿正能量、努力生活
個性簽名能夠反映人的一種心態,對全部好友的個性簽名進行分詞後製做以下詞雲圖:
從詞雲圖中能夠看到,微信好友個性簽名中出現頻率較高的詞彙有:本身、努力、生活、世界、就是、咱們、人生、沒有、須要、不要、時間、一切、一塊兒、永遠、將來、運動、快樂、溫柔、個性等,總體來看,個人微信好友仍是充滿正能量的,都是積極向上、努力生活、有個性的年青人。
咱們能夠來詳細的分析下這些高頻詞:
本身、就是、咱們、個性: 彰顯個性的自我、自覺得是、自大等,也說明了年青人的個性張揚、無所畏懼
努力、生活、時間、須要: 說明你們都在努力的工做,追求各自所需,爲更好的生活拼博着
世界、人生、快樂、將來: 正所謂「世界那麼大,我想去看看」,生活雖不易,但對外面的世界、對人生的追求從未中止過,快樂最重要
運動、健康、溫柔、享受: 說明喜歡運動的朋友比較多,你們都愈來愈關注健康。溫柔、享受也成爲共識,活着不易,且活且享受。
4. 備註名詞雲圖
獲取好友的備註名,根據備註名生成詞名圖
代碼實現:
#!/usr/bin/env python3 # -*- coding: utf-8 -*- # 導入jieba模塊,用於中文分詞 import jieba # 導入matplotlib,用於生成2D圖形 import matplotlib.pyplot as plt # 導入wordcount,用於製做詞雲圖 from wordcloud import WordCloud, STOPWORDS # 獲取備註名 remarkNames = [] with open('friends.txt', mode='r', encoding='utf-8') as f: rows = f.readlines() for row in rows: remarkName = row.split(',')[1] if remarkName != '': remarkNames.append(remarkName) # 設置分詞 split = jieba.cut(str(remarkNames), cut_all=False) # False精準模式分詞、True全模式分詞 words = ' '.join(split) # 以空格進行拼接 print(words) # 導入背景圖 bg_image = plt.imread('bg.jpg') # 設置詞雲參數,參數分別表示:畫布寬高、背景顏色、背景圖形狀、字體、屏蔽詞、最大詞的字體大小 wc = WordCloud(width=1024, height=768, background_color='white', mask=bg_image, font_path='STKAITI.TTF', max_font_size=400, random_state=50) # 將分詞後數據傳入雲圖 wc.generate_from_text(words) plt.imshow(wc) # 繪製圖像 plt.axis('off') # 不顯示座標軸 # 保存結果到本地 wc.to_file('備註名詞雲圖.jpg')
可視化結果:
好友備註中「跑友」、「南航」出現的頻率最高
從圖中能夠看出,個人好友備註中出現的高頻詞有:跑友、南航、wbs1709一、wbs1803一、wbs1702二、wbs17071等
本人平時喜歡跑步,也常常參加各類馬拉松活動,認識的跑友比較多,因此不足爲奇
因爲工做上與南航有必定的交集,因此南航的好友也比較多
以wbs開頭的備註都是我工做中帶過的學生,數量衆多,身爲一名IT教育工做者,深感光榮。
重要說明:考慮我的隱私,圖中部分姓名作了化名處理,請勿當真,若有不便,還望諒解。
5. 好友分類分析
根據備註名,對好友進行分類,統計各種好友的數量
PS:個人習慣是對好友添加備註,標記好友的類型或來源,這屬於我的潔癖的一種吧
代碼實現:
#!/usr/bin/env python3 # -*- coding: utf-8 -*- # 導入jieba模塊,用於中文分詞 import jieba # 導入Counter類,用於統計值出現的次數 from collections import Counter from pyecharts import Bar # 獲取備註名 remarkNames = [] with open('friends.txt', mode='r', encoding='utf-8') as f: rows = f.readlines() for row in rows: remarkName = row.split(',')[1] if remarkName != '': remarkNames.append(remarkName) # 設置分詞 words = [x for x in jieba.cut(str(remarkNames), cut_all=False) if x not in ['-', ',', '(', ')', '(', ')', ' ', "'"]] # 排除短橫線、逗號、空格、單引號 data_top10 = Counter(words).most_common(10) # 返回出現次數最多的20條 print(data_top10) bar = Bar('好友分類TOP10', '', title_pos='center', width=1200, height=600) attr, value = bar.cast(data_top10) bar.add('', attr, value, visual_range=[0, 200], is_visualmap=True, is_label_show=True) bar.render('好友分類TOP10.html')
可視化結果:
學生最多,其次是跑友
這裏只統計好友分類數量最多的前10,其中跑友160人,南航52人,其餘的都是wbs開頭的學生,實際上wbs開頭的學生數是最多的,只是在備註時按班級號進行了劃分。
經過分析統計,本身對各種好友的數量也作到了心中有數。
6. 特殊好友分析
獲取並統計如下的特殊好友: 星標好友 、 不讓他看個人朋友圈 、 不看他的朋友圈
代碼實現:
#!/usr/bin/env python3 # -*- coding: utf-8 -*- from pyecharts import Bar # 獲取特殊好友 star_list = [] # 星標朋友 deny_see_list = [] # 不讓他看個人朋友圈 no_see_list = [] # 不看他的朋友圈 with open('friends.txt', mode='r', encoding='utf-8') as f: rows = f.readlines() for row in rows: # # 獲取好友名稱 name = row.split(',')[1] if row.split(',')[1] != '' else row.split(',')[0] # 獲取星標朋友 star = row.split(',')[6] if star == '1': star_list.append(name) # 獲取設置了朋友圈權限的朋友 flag = row.split(',')[7].replace('\n', '') if flag in ['259', '33027', '65795']: deny_see_list.append(name) if flag in ['65539', '65795']: no_see_list.append(name) print('星標好友:', star_list) print('不讓他看個人朋友圈:', deny_see_list) print('不看他的朋友圈:', no_see_list) attr = ['星標朋友', '不讓他看個人朋友圈', '不看他的朋友圈'] value = [len(star_list), len(deny_see_list), len(no_see_list)] bar = Bar('特殊好友分析', '', title_pos='center') bar.add('', attr, value, is_visualmap=True, is_label_show=True) bar.render('特殊好友分析.html')
可視化結果:
特殊好友。。。你懂的
從上圖中能夠發現:
星標好友有4個,主要是特別關注的好友,我的以爲比較重要的朋友
不讓他看個人朋友圈有30個,這類好友通常是比較陌生的人,瞭解較少,固然也有個別是以爲不太方便的
不看他的朋友圈有8個,這類基本上都是隻在朋友圈發廣告的,除了廣告沒有別的內容,並且每次連續性的發多條,看着確實有些煩
補充說明:在代碼中有對特殊好友的姓名也進行了輸出顯示,你們在運行代碼時能夠在控制檯查看特殊好友具體是誰
7. 好友頭像分析
使用騰訊優圖提供的人臉識別技術,對頭像進行檢測和分
首先獲取全部好友的頭像:
import itchat import os # 獲取數據 def get_image(): itchat.auto_login() friends = itchat.get_friends(update=True) # 在當前位置建立一個用於存儲頭像的目錄headImages base_path = 'headImages' if not os.path.exists(base_path): os.mkdir(base_path) # 獲取全部好友頭像 for friend in friends: img_data = itchat.get_head_img(userName=friend['UserName']) # 獲取頭像數據 img_name = friend['RemarkName'] if friend['RemarkName'] != '' else friend['NickName'] img_file = os.path.join(base_path, img_name + '.jpg') print(img_file) with open(img_file, 'wb') as file: file.write(img_data) if __name__ == '__main__': get_data()
對頭像進行人臉檢測,檢測頭像圖片中是否存在人臉,統計使用人臉做用頭像的佔比。
補充說明:
使用騰訊優圖相關服務須要在其平臺上申請開發者帳戶,並獲取審覈後的密鑰,具體步驟參考官網
在進行人臉檢測時速度會比較慢,頭像數量不一樣須要等待的時間也會有所不一樣,個人好友有900多,大概花了10分鐘左右
# 導入騰訊優圖,用來實現人臉檢測等功能 import TencentYoutuyun from pyecharts import Pie def analyse_data(): # 向騰訊優圖平臺申請的開發密鑰,此處須要替換爲本身的密鑰 appid = '********' secret_id = '************************' secret_key = '************************' userid = '******** end_point = TencentYoutuyun.conf.API_YOUTU_END_POINT # 優圖開放平臺 youtu = TencentYoutuyun.YouTu(appid, secret_id, secret_key, userid, end_point) use_face = 0 not_use_face = 0 base_path = 'headImages' for file_name in os.listdir(base_path): result = youtu.DetectFace(os.path.join(base_path, file_name)) # 人臉檢測與分析 # print(result) # 參考 https://open.youtu.qq.com/legency/#/develop/api-face-analysis-detect # 判斷是否使用人像 if result['errorcode'] == 0: # errorcode爲0表示圖片中存在人像 use_face += 1 gender = '男' if result['face'][0]['gender'] >= 50 else '女' age = result['face'][0]['age'] beauty = result['face'][0]['beauty'] # 魅力值 glasses = '不戴眼鏡 ' if result['face'][0]['glasses'] == 0 else '戴眼鏡' # print(file_name[:-4], gender, age, beauty, glasses, sep=',') with open('header.txt', mode='a', encoding='utf-8') as f: f.write('%s,%s,%d,%d,%s\n' % (file_name[:-4], gender, age, beauty, glasses)) else: not_use_face += 1 attr = ['使用人臉頭像', '未使用人臉頭像'] value = [use_face, not_use_face] pie = Pie('好友頭像分析', '', title_pos='center') pie.add('', attr, value, radius=[30, 75], is_label_show=True, is_legend_show=True, legend_top='bottom') # pie.show_config() pie.render('好友頭像分析.html') if __name__ == '__main__': analyse_data()
可視化結果:
使用人臉頭臉的好友並不算多,佔比31%
從上圖中能夠看到,使用人臉頭像的好友並很少,佔比30.87%,大部分都未使用人臉頭像,佔比69.13%,從某個角度能夠反應出這部分人不肯過多的暴露本身,或是對自我顏值的不自信,具體狀況要看我的的心態了。
對於使用人臉頭像的,還能夠檢測圖片中人臉的性別、年齡、魅力值、是否戴眼鏡等(考慮到我的隱私,部分信息作了處理)。
咱們還能夠將全部頭像拼接在一塊兒,生成一個微信好友頭像拼接圖:
# 拼接頭像 def join_image(): base_path = 'headImages' files = os.listdir(base_path) each_size = int(math.sqrt(float(640 * 640) / len(files))) lines = int(640 / each_size) image = Image.new('RGB', (640, 640)) x = 0 y = 0 for file_name in files: img = Image.open(os.path.join(base_path, file_name)) img = img.resize((each_size, each_size), Image.ANTIALIAS) image.paste(img, (x * each_size, y * each_size)) x += 1 if x == lines: x = 0 y += 1 image.save('all.jpg') itchat.send_image('all.jpg', 'filehelper')
生成的頭像拼接圖,有密集恐懼症的請跳過 ^_^