微信好友大揭秘,使用Python抓取朋友圈数据,通过人脸识别全面分析好友,一起看透你的“朋友圈”...
微信:一個提供即時通訊服務的應用程序,更是一種生活方式,超過數(shù)十億的使用者,越來越多的人選擇使用它來溝通交流。
不知從何時起,我們的生活離不開微信,每天睜開眼的第一件事就是打開微信,關注著朋友圈里好友的動態(tài),而朋友圈中或虛或實的狀態(tài)更新,似乎都在證明自己的“有趣”,尋找那份或有或無的存在感。
有人選擇在朋友圈記錄生活的點滴,有人選擇在朋友圈展示自己的觀點。有時我們想去展示自己,有時又想去窺探著別人的生活,而有時又不想別人過多的了解自己的生活,或是屏蔽對方,或是不給對方看朋友圈,又或是不想看對方的朋友圈。
作者本人(湯小洋 )也是微信的重度依賴者,每天的工作生活都離不開它,也會關注朋友圈里好友的動態(tài),我個人認為微信朋友圈是一種文化的體現(xiàn),諸如:發(fā)圈、點贊、留言等,都能側面的反應一個人的生活、工作、心態(tài)、愛好、修養(yǎng)、上進心、努力程度等。
今天就跟著 湯老師 一起來揭秘微信朋友圈,利用 Python+AI人工智能 進行多角度分析,一起看透你的“朋友圈”。
我們將使用Python抓取朋友圈數(shù)據(jù),并對獲取到的數(shù)據(jù)進行全面分析,包含好友性別、地理位置分布、個性簽名、備注名、好友類型等,逐一進行分析,同時還會使用人臉識別技術對好友頭像進行分析,分析到你懷疑人生。。。。。。
整個過程分為四步:
一、獲取數(shù)據(jù)
? 關于微信好友數(shù)據(jù)的獲取,可以通過itchat庫,itchat是一個開源的微信個人號的接口,可以實現(xiàn)信息收發(fā)、獲取好友列表等功能。
? 具體的用法和說明,在代碼中已經做了詳細的注釋。
#!/usr/bin/env python3 # -*- coding: utf-8 -*- __author__ = '湯小洋'# 導入itchat模塊,操作微信個人號的接口 import itchat# 獲取數(shù)據(jù) def get_data():# 掃描二維碼登陸微信,實際上就是通過網(wǎng)頁版微信登陸itchat.auto_login()# 獲取所有好友信息friends = itchat.get_friends(update=True) # 返回一個包含用戶信息字典的列表return friendsif __name__ == '__main__':print(get_data())? 執(zhí)行代碼時電腦屏幕會出現(xiàn)一個二維碼,手機微信掃描后即可完成登陸
二、處理數(shù)據(jù)
? 對獲取的數(shù)據(jù)進行處理,篩選出需要的數(shù)據(jù)。
? 通過對返回的用戶信息進行分析,發(fā)現(xiàn)列表中第一個元素是用戶自己,可以排除掉。同時我們只取需要的字段數(shù)據(jù),各個字段及其取值的含義已在代碼中做了說明。
# 處理數(shù)據(jù) 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 friendsif __name__ == '__main__':print(parse_data(get_data()))三、存儲數(shù)據(jù)
? 為了便于分析數(shù)據(jù)并進行可視化操作,這里將數(shù)據(jù)存儲到文本文件中。
# 存儲數(shù)據(jù),存儲到文本文件 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()? 重要說明:這里我獲取的是自己的微信好友數(shù)據(jù)(共計950條,因工作關系,好友數(shù)比較多),考慮到個人隱私,部分信息做了處理。
四、數(shù)據(jù)可視化
? 這里使用的是pyecharts,pyecharts是一個用于生成Echarts圖表的類庫,便于在Python中根據(jù)數(shù)據(jù)生成可視化的圖表。
? Echarts是百度開源的一個數(shù)據(jù)可視化JS庫,主要用于數(shù)據(jù)可視化。
? 參考:http://pyecharts.org/
# 安裝pyecharts pip install pyecharts1. 好友性別分析
? 代碼實現(xiàn):
#!/usr/bin/env python3 # -*- coding: utf-8 -*- __author__ = '湯小洋'# 導入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)# 統(tǒng)計每個性別的數(shù)量 attr = ['帥哥', '美女', '未知'] value = [sex.count('1'), sex.count('2'), sex.count('0')]pie = Pie('好友性別比例', '好友總人數(shù):%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%,男女比例嚴重失衡
看到這個結果,我是有些淡淡憂桑的,微信好友總人數(shù)為950,帥哥占比70.42%,美女占比24.53%,男女比例嚴重失衡,但一點也不意外,本人是一名IT工作者,平時喜歡跑步,所以工作、生活接觸到的大部分都是男性朋友,出現(xiàn)男女比例失衡實屬正常。
2. 好友位置分析
pyecharts v0.3.2以后,pyecharts 將不再自帶地圖 js 文件。如用戶需要用到地圖圖表,可自行安裝對應的地圖文件包。
# 安裝地圖文件包 pip install echarts-china-provinces-pypkg # 中國省、市、縣、區(qū)地圖 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代碼實現(xiàn):
# 導入Counter類,用于統(tǒng)計值出現(xiàn)的次數(shù) from collections import Counter # 導入Geo組件,用于生成地理坐標類圖 from pyecharts import Geo import json # 導入Bar組件,用于生成柱狀圖 from pyecharts import Bar# 數(shù)據(jù)可視化 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)# 對城市數(shù)據(jù)和坐標文件中的地名進行處理handle(cities)# 統(tǒng)計每個城市出現(xiàn)的次數(shù)data = Counter(cities).most_common() # 使用Counter類統(tǒng)計出現(xiàn)的次數(shù),并轉換為元組列表print(data)# 根據(jù)城市數(shù)據(jù)生成地理坐標圖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')# 根據(jù)城市數(shù)據(jù)生成柱狀圖data_top20 = Counter(cities).most_common(20) # 返回出現(xiàn)次數(shù)最多的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')出現(xiàn)的問題:
-
報錯:ValueError: No coordinate is specified for xxx(地名)
-
原因:pyecharts的坐標文件中沒有該地名,實際上是名稱不一致導致的,如數(shù)據(jù)中地名為'達州',而坐標文件中為'達州市'
坐標文件所在路徑:項目/venv/lib/python3.6/site-packages/pyecharts/datasets/city_coordinates.json
- 解決:修改坐標文件,在原位置下復制個同樣的,然后修改下地名
不過由于要修改的地名太多,上面的方法實在是麻煩,所以我定義了一個函數(shù),用來處理地名數(shù)據(jù)找不到的問題
# 處理地名數(shù)據(jù),解決坐標文件中找不到地名的問題 def handle(cities):# print(len(cities), len(set(cities)))# 獲取坐標文件中所有地名data = Nonewith 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# 循環(huán)判斷處理data_new = data.copy() # 拷貝所有地名數(shù)據(jù)for city in set(cities): # 使用set去重# 處理地名為空的數(shù)據(jù)if city == '':while city in cities:cities.remove(city)count = 0for k in data.keys():count += 1if k == city:breakif k.startswith(city): # 處理簡寫的地名,如 達州市 簡寫為 達州# print(k, city)data_new[city] = data[k]breakif k.startswith(city[0:-1]) and len(city) >= 3: # 處理行政變更的地名,如縣改區(qū) 或 縣改市等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可視化結果:
好友主要集中在江蘇及周邊地區(qū)
從圖中可以發(fā)現(xiàn):我的微信好友主要集中在江蘇及周邊地區(qū),本人大學讀書時來到南京,現(xiàn)在工作生活也一直在南京,所以南京好友最多,為483個;我自小在徐州長大,所以徐州好友數(shù)量也較多;同時因為喜歡跑步,結識了許多跑友,也經常會到周邊沿海城市參加各種馬拉松活動,所以好友位置主要分布在沿海一帶。
3. 個性簽名詞云圖
? jieba是一個基于Python的分詞庫,完美支持中文分詞,功能強大
pip install jieba? Matplotlib是一個Python的2D繪圖庫,能夠生成高質量的圖形,可以快速生成繪圖、直方圖、功率譜、柱狀圖、誤差圖、散點圖等
pip install matplotlib? wordcloud是一個基于Python的詞云生成類庫,可以生成詞云圖
pip install wordcloud? 代碼實現(xiàn):
#!/usr/bin/env python3 # -*- coding: utf-8 -*- __author__ = '湯小洋'# 導入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')# 設置詞云參數(shù),參數(shù)分別表示:畫布寬高、背景顏色、背景圖形狀、字體、屏蔽詞、最大詞的字體大小 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) # 將分詞后數(shù)據(jù)傳入云圖 wc.generate_from_text(words) plt.imshow(wc) # 繪制圖像 plt.axis('off') # 不顯示坐標軸 # 保存結果到本地 wc.to_file('個性簽名詞云圖.jpg')可視化結果:
充滿正能量、努力生活
? 個性簽名可以反映人的一種心態(tài),對所有好友的個性簽名進行分詞后制作如下詞云圖:
? 從詞云圖中可以看到,微信好友個性簽名中出現(xiàn)頻率較高的詞匯有:自己、努力、生活、世界、就是、我們、人生、沒有、需要、不要、時間、一切、一起、永遠、未來、運動、快樂、溫柔、個性等,整體來看,我的微信好友還是充滿正能量的,都是積極向上、努力生活、有個性的年青人。
? 我們可以來詳細的分析下這些高頻詞:
- 自己、就是、我們、個性:彰顯個性的自我、自以為是、自大等,也說明了年青人的個性張揚、無所畏懼
- 努力、生活、時間、需要:說明大家都在努力的工作,追求各自所需,為更好的生活拼博著
- 世界、人生、快樂、未來:正所謂“世界那么大,我想去看看”,生活雖不易,但對外面的世界、對人生的追求從未停止過,快樂最重要
- 運動、健康、溫柔、享受:說明喜歡運動的朋友比較多,大家都越來越關注健康。溫柔、享受也成為共識,活著不易,且活且享受。
4. 備注名詞云圖
? 獲取好友的備注名,根據(jù)備注名生成詞名圖
? 代碼實現(xiàn):
#!/usr/bin/env python3 # -*- coding: utf-8 -*- __author__ = '湯小洋'# 導入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')# 設置詞云參數(shù),參數(shù)分別表示:畫布寬高、背景顏色、背景圖形狀、字體、屏蔽詞、最大詞的字體大小 wc = WordCloud(width=1024, height=768, background_color='white', mask=bg_image, font_path='STKAITI.TTF',max_font_size=400, random_state=50) # 將分詞后數(shù)據(jù)傳入云圖 wc.generate_from_text(words) plt.imshow(wc) # 繪制圖像 plt.axis('off') # 不顯示坐標軸 # 保存結果到本地 wc.to_file('備注名詞云圖.jpg')可視化結果:
好友備注中“跑友”、“南航”出現(xiàn)的頻率最高
? 從圖中可以看出,我的好友備注中出現(xiàn)的高頻詞有:跑友、南航、wbs17091、wbs18031、wbs17022、wbs17071等
- 本人平時喜歡跑步,也經常參加各種馬拉松活動,認識的跑友比較多,所以不足為奇
- 由于工作上與南航有一定的交集,所以南航的好友也比較多
-
以wbs開頭的備注都是我工作中帶過的學生,數(shù)量眾多,身為一名IT教育工作者,深感光榮。
重要說明:考慮個人隱私,圖中部分姓名做了化名處理,請勿當真,如有不便,還望諒解。
5. 好友分類分析
? 根據(jù)備注名,對好友進行分類,統(tǒng)計各類好友的數(shù)量
? PS:我的習慣是對好友添加備注,標記好友的類型或來源,這屬于個人潔癖的一種吧
? 代碼實現(xiàn):
#!/usr/bin/env python3 # -*- coding: utf-8 -*- __author__ = '湯小洋'# 導入jieba模塊,用于中文分詞 import jieba # 導入Counter類,用于統(tǒng)計值出現(xiàn)的次數(shù) 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) # 返回出現(xiàn)次數(shù)最多的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')可視化結果:
學生最多,其次是跑友
這里只統(tǒng)計好友分類數(shù)量最多的前10,其中跑友160人,南航52人,其他的都是wbs開頭的學生,實際上wbs開頭的學生數(shù)是最多的,只是在備注時按班級號進行了劃分。
通過分析統(tǒng)計,自己對各類好友的數(shù)量也做到了心中有數(shù)。
6. 特殊好友分析
? 獲取并統(tǒng)計以下的特殊好友:星標好友、不讓他看我的朋友圈、不看他的朋友圈
? 代碼實現(xiàn):
#!/usr/bin/env python3 # -*- coding: utf-8 -*- __author__ = '湯小洋' 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')可視化結果:
特殊好友。。。你懂的
從上圖中可以發(fā)現(xiàn):
- 星標好友有4個,主要是特別關注的好友,個人覺得比較重要的朋友
- 不讓他看我的朋友圈有30個,這類好友一般是比較陌生的人,了解較少,當然也有個別是覺得不太方便的
- 不看他的朋友圈有8個,這類基本上都是只在朋友圈發(fā)廣告的,除了廣告沒有別的內容,而且每次連續(xù)性的發(fā)多條,看著確實有些煩
補充說明:在代碼中有對特殊好友的姓名也進行了輸出顯示,大家在運行代碼時可以在控制臺查看特殊好友具體是誰
7. 好友頭像分析
? 使用騰訊優(yōu)圖提供的人臉識別技術,對頭像進行檢測和分析,相關API接口及使用請參考:https://open.youtu.qq.com/legency/#/develop/new-join
? 首先獲取所有好友的頭像:
import itchat import os# 獲取數(shù)據(jù) def get_image():itchat.auto_login()friends = itchat.get_friends(update=True)# 在當前位置創(chuàng)建一個用于存儲頭像的目錄headImagesbase_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']) # 獲取頭像數(shù)據(jù)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()? 對頭像進行人臉檢測,檢測頭像圖片中是否存在人臉,統(tǒng)計使用人臉作用頭像的占比。
? 補充說明:
- 使用騰訊優(yōu)圖相關服務需要在其平臺上申請開發(fā)者賬戶,并獲取審核后的密鑰,具體步驟參考官網(wǎng)
- 在進行人臉檢測時速度會比較慢,頭像數(shù)量不同需要等待的時間也會有所不同,我的好友有900多,大概花了10分鐘左右
可視化結果:
使用人臉頭臉的好友并不算多,占比31%
從上圖中可以看到,使用人臉頭像的好友并不多,占比30.87%,大部分都未使用人臉頭像,占比69.13%,從某個角度可以反應出這部分人不愿過多的暴露自己,或是對自我顏值的不自信,具體情況要看個人的心態(tài)了。
對于使用人臉頭像的,還可以檢測圖片中人臉的性別、年齡、魅力值、是否戴眼鏡等(考慮到個人隱私,部分信息做了處理)。
?
我們還可以將所有頭像拼接在一起,生成一個微信好友頭像拼接圖:
# 拼接頭像 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 = 0y = 0for 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 += 1if x == lines:x = 0y += 1image.save('all.jpg')itchat.send_image('all.jpg', 'filehelper')生成的頭像拼接圖,有密集恐懼癥的請?zhí)^ ^_^
附:
Python基礎入門視頻課程:http://edu.51cto.com/course/14859.html
Python爬蟲視頻課程:http://edu.51cto.com/course/14870.html
轉載于:https://blog.51cto.com/12402007/2178703
總結
以上是生活随笔為你收集整理的微信好友大揭秘,使用Python抓取朋友圈数据,通过人脸识别全面分析好友,一起看透你的“朋友圈”...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 阿里云OSS 服务端签名后直传之分片上
- 下一篇: mysql优化学习(二)