1. 程式人生 > >用Python抓取朋友圈資料,通過人臉識別全面分析好友!看透朋友圈

用Python抓取朋友圈資料,通過人臉識別全面分析好友!看透朋友圈

微信:一個提供即時通訊服務的應用程式,更是一種生活方式,超過數十億的使用者,越來越多的人選擇使用它來溝通交流。

不知從何時起,我們的生活離不開微信,每天睜開眼的第一件事就是開啟微信,關注著朋友圈裡好友的動態,而朋友圈中或虛或實的狀態更新,似乎都在證明自己的“有趣”,尋找那份或有或無的存在感。

進群:865597862 即可獲取數十套PDF哦!

image.png

image.png

獲取資料

處理資料

儲存資料

資料視覺化

一、獲取資料

​ 關於微信好友資料的獲取,可以通過itchat庫,itchat是一個開源的微信個人號的介面,可以實現資訊收發、獲取好友列表等功能。

​ 具體的用法和說明,在程式碼中已經做了詳細的註釋。

!/usr/bin/env python3

-- coding: utf-8 --

author = '湯小洋'

匯入itchat模組,操作微信個人號的介面

import itchat

獲取資料

def get_data():

掃描二維碼登陸微信,實際上就是通過網頁版微信登陸

itchat.auto_login()

獲取所有好友資訊

friends = itchat.get_friends(update=True) # 返回一個包含使用者資訊字典的列表

return friends

if name == 'main':

print(get_data())

​ 執行程式碼時電腦螢幕會出現一個二維碼,手機微信掃描後即可完成登陸

二維碼就不帶了!

二、處理資料

​ 對獲取的資料進行處理,篩選出需要的資料。

​ 通過對返回的使用者資訊進行分析,發現列表中第一個元素是使用者自己,可以排除掉。同時我們只取需要的欄位資料,各個欄位及其取值的含義已在程式碼中做了說明。

處理資料

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('', ' ').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()))

三、儲存資料

​ 為了便於分析資料並進行視覺化操作,這裡將資料儲存到文字檔案中。

儲存資料,儲存到文字檔案

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' % (

item['NickName'], item['RemarkName'], item['Sex'], item['Province'], item['City'], item['Signature'],

item['StarFriend'], item['ContactFlag']))

if name == 'main':

save_to_txt()

​ 重要說明: 這裡我獲取的是自己的微信好友資料(共計950條,因工作關係,好友數比較多),考慮到個人隱私,部分資訊做了處理。

image.png

四、資料視覺化

​ 這裡使用的是pyecharts,pyecharts是一個用於生成Echarts圖表的類庫,便於在Python中根據資料生成視覺化的圖表。

​ Echarts是百度開源的一個數據視覺化JS庫,主要用於資料視覺化。

安裝pyecharts

pip install pyecharts

1. 好友性別分析

​ 程式碼實現:

!/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)

統計每個性別的數量

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%,男女比例嚴重失衡

image.png

看到這個結果,我是有些淡淡憂桑的,微信好友總人數為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

視覺化結果:

好友主要集中在江蘇及周邊地區

image.png

image.png

從圖中可以發現:我的微信好友主要集中在江蘇及周邊地區,本人大學讀書時來到南京,現在工作生活也一直在南京,所以南京好友最多,為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 --

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')

設定詞雲引數,引數分別表示:畫布寬高、背景顏色、背景圖形狀、字型、遮蔽詞、最大詞的字型大小

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 --

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')

設定詞雲引數,引數分別表示:畫布寬高、背景顏色、背景圖形狀、字型、遮蔽詞、最大詞的字型大小

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')

視覺化結果:

好友備註中“跑友”、“南航”出現的頻率最高

image.png

​ 從圖中可以看出,我的好友備註中出現的高頻詞有:跑友、南航、wbs17091、wbs18031、wbs17022、wbs17071等

本人平時喜歡跑步,也經常參加各種馬拉松活動,認識的跑友比較多,所以不足為奇

由於工作上與南航有一定的交集,所以南航的好友也比較多

以wbs開頭的備註都是我工作中帶過的學生,數量眾多,身為一名IT教育工作者,深感光榮。

重要說明:考慮個人隱私,圖中部分姓名做了化名處理,請勿當真,如有不便,還望諒解。

5. 好友分類分析

​ 根據備註名,對好友進行分類,統計各類好友的數量

​ PS:我的習慣是對好友新增備註,標記好友的型別或來源,這屬於個人潔癖的一種吧

​ 程式碼實現:

!/usr/bin/env python3

-- coding: utf-8 --

author = '湯小洋'

匯入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')

視覺化結果:

學生最多,其次是跑友

image.png

這裡只統計好友分類數量最多的前10,其中跑友160人,南航52人,其他的都是wbs開頭的學生,實際上wbs開頭的學生數是最多的,只是在備註時按班級號進行了劃分。

通過分析統計,自己對各類好友的數量也做到了心中有數。

6. 特殊好友分析

​ 獲取並統計以下的特殊好友: 星標好友 、 不讓他看我的朋友圈 、 不看他的朋友圈

​ 程式碼實現:

!/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('', '')

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')

視覺化結果:

特殊好友。。。你懂的

image.png

從上圖中可以發現:

星標好友有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)) # 人臉檢測與分析

判斷是否使用人像

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' % (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%

image.png

從上圖中可以看到,使用人臉頭像的好友並不多,佔比30.87%,大部分都未使用人臉頭像,佔比69.13%,從某個角度可以反應出這部分人不願過多的暴露自己,或是對自我顏值的不自信,具體情況要看個人的心態了。

對於使用人臉頭像的,還可以檢測圖片中人臉的性別、年齡、魅力值、是否戴眼鏡等(考慮到個人隱私,部分資訊做了處理)。

image.png

我們還可以將所有頭像拼接在一起,生成一個微信好友頭像拼接圖:

拼接頭像

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')

生成的頭像拼接圖,有密集恐懼症的請跳過 _

image.png

原始碼不分享了哦