初學Python的時候,就寫過一篇利用Python的第三方庫進行好友頭像拼接,itchat
itchat庫初探--微信好友全頭像的拼接,最近又研究了下itchat和matplotlib,目前實現了對微信好友頭像、性別、區域、個性簽名的採集及展現。html
本文就來詳細介紹一下這個庫的用法和一些核心邏輯實現。python
hotReload=True
import itchat
itchat.auto_login(hotReload=True)
itchat.dump_login_status()
複製代碼
we_friend = itchat.get_friends(update=True)[:]
複製代碼
這裏的we_friend
是好友的信息的列表,每個好友字典的 key 以下表git
key | 備註 |
---|---|
UserName | 微信系統內的用戶編碼標識 |
NickName | 好友暱稱 |
Sex | 性別 |
Province | 省份 |
City | 城市 |
HeadImgUrl | 微信系統內的頭像URL |
RemarkName | 好友的備註名 |
Signature | 個性簽名 |
有了key對應的值,咱們就好處理了。github
這裏順便提一下:若是sex=1則表明男性,sex=2表明女性api
total = len(we_friend[1:])
for fri_info in we_friend[1:]:
sex = fri_info['sex']
# 若是sex=1 表明男性 sex=2表明女性
if sex == 1:
man += 1
elif sex == 2:
woman += 1
else:
other += 1
複製代碼
統計出男生、女生的以及總人數後,佔比天然而然就出來了,爲了更好的展現男女比例,咱們以餅圖展現。緩存
man_ratio = int(man)/total * 100
woman_ratio = int(woman)/total * 100
other_ratio = int(other)/total * 100
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用來正常顯示中文標籤
plt.rcParams['axes.unicode_minus'] = False # 用來正常顯示負號
plt.figure(figsize=(5, 5)) # 繪製的圖片爲正圓
sex_li = ['男', '女', '其餘']
radius = [0.01, 0.01, 0.01] # 設定各項距離圓心n個半徑
colors = ['red', 'yellowgreen', 'lightskyblue']
proportion = [man_ratio, woman_ratio, other_ratio]
plt.pie(proportion, explode=radius, labels=sex_li, colors=colors, autopct='%.2f%%') # 繪製餅圖
# 加入圖例 loc = 'upper right' 位於右上角 bbox_to_anchor=[0.5, 0.5] # 外邊距 上邊 右邊 borderaxespad = 0.3圖例的內邊距
plt.legend(loc="upper right", fontsize=10, bbox_to_anchor=(1.1, 1.1), borderaxespad=0.3)
# 繪製標題
plt.title('微信好友性別比例')
# 展現
plt.show()
複製代碼
做爲一個碼農、程序猿,還能有這麼多女性好友實屬不易啊。敏感的我,看了這個比例深深地感受到了不安,(此圖女友不可見)另外,怎麼還有一些未知生物的存在...bash
友情提醒:matplotlib中文亂碼這個問題一直存在,這裏記錄下如何解決matplotlib中文亂碼微信
import matplotlib
print(matplotlib.matplotlib_fname()) # 查看路徑
複製代碼
進入上方打印的路徑app
把剛纔下載的字體文件解壓放入/usr/local/lib/python3.5/dist-packages/matplotlib/mpl-data/fonts/ttf
目錄dom
返回上級目錄,修改matplotlibrc文件,取消相關注釋,並在font.serif
加入剛纔下載的字體
font.family : sans-serif
font.serif : SimHei, DejaVu Serif, Bitstream Vera Serif, New Century Schoolbook, Century Schoolbook L, Utopia, ITC Bookman, Bookman, Nimbus Roman No9 L, Times New Roman, Times, Palatino, Charter, serif
複製代碼
在terminal中:cd ~/.cache/matplotlib
把.cache下面的matplotlib文件夾刪除。
$ rm -rf matplotlib
複製代碼
這裏其實看過我以前文章的應該知道,其實頭像的拼接主要分爲兩部分
import os
num = 0
pwd_path = os.path.abspath(os.path.dirname(os.getcwd()))
desc_photos = os.path.join(pwd_path, 'res/photos')
for i in friends:
img = itchat.get_head_img(userName=i["UserName"])
file_image = open(desc_photos + "/" + str(num) + ".jpg", 'wb')
file_image.write(img)
file_image.close()
num += 1
複製代碼
ls = os.listdir(desc_photos)
each_size = int(math.sqrt(float(640 * 640) / len(ls))) # 算出每張圖片的大小多少合適
lines = int(640 / each_size)
image = Image.new('RGBA', (640, 640)) # 建立640*640px的大圖
x = 0
y = 0
for i in range(0, len(ls) + 1):
try:
img = Image.open(desc_photos + "/" + str(i) + ".jpg")
except IOError:
print("Error")
else:
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(desc_full + "/好友頭像拼接圖.jpg")
複製代碼
密集恐懼症患者請忽略!!!
-- 獲取區域及城市
prov_dict, city_dict = {}, {}
for fri_info in we_friend[1:]:
prov = fri_info['province']
city = fri_info['city']
if prov and prov not in prov_dict.keys():
prov_dict[prov] = 1
elif prov:
prov_dict[prov] += 1
if city and city not in city_dict.keys():
city_dict[city] = 1
elif city:
city_dict[city] += 1
複製代碼
因爲城市太多,咱們取好友數量排名前十的城市及區域進行展現,感興趣的能夠稍微改下代碼,就能夠展現全部區域人數。
排序這裏我用了Python的sorted()
函數,列表的每一個元素都爲二維元組,key
參數傳入了一個lambda函數
,其x就表明列表裏的每個元素,而後分別利用索引返回元素內的第一個和第二個元素,這就表明了sorted()
函數利用哪個元素進行排列。而reverse
決定是正序仍是倒序,默認爲False。
# 區域Top10
prov_dict_top10 = sorted(prov_dict.items(), key=lambda x: x[1], reverse=True)[0:10]
# 城市Top10
city_dict_top10 = sorted(city_dict.items(), key=lambda y: y[1], reverse=True)[0:10]
複製代碼
prov_nm, prov_num = [], [] # 省會名 + 數量
for prov_data in prov_dict_top10:
prov_nm.append(prov_data[0])
prov_num.append(prov_data[1])
pwd_path = os.path.abspath(os.path.dirname(os.getcwd()))
desc_full = os.path.join(pwd_path, 'res')
colors = ['#00FFFF', '#7FFFD4', '#F08080', '#90EE90', '#AFEEEE',
'#98FB98', '#B0E0E6', '#00FF7F', '#FFFF00', '#9ACD32']
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用來正常顯示中文標籤
plt.rcParams['axes.unicode_minus'] = False # 用來正常顯示負號
index = range(len(prov_num))
plt.bar(index, prov_num, color=colors, width=0.5, align='center')
plt.xticks(range(len(prov_nm)), prov_nm) # 橫坐軸標籤
for x, y in enumerate(prov_num):
# 在柱子上方1.2處標註值
plt.text(x, y + 1.2, '%s' % y, ha='center', fontsize=10)
plt.ylabel('省會好友人數') # 設置縱座標標籤
prov_title = '微信好友區域Top10'
plt.title(prov_title) # 設置標題
plt.savefig(desc_full + '/微信好友區域Top10') # 保存圖片
複製代碼
經過柱形圖展現,能夠清晰看到個人好友主要分佈在河南和上海,藉此不難推測出個人工做地址以及戶籍所在地。
這裏使用了經常使用的中文分詞庫jieba
,詞雲圖的背景採用了萌萌大小豬佩奇(´๑•_•๑)
sign_li = []
rule = re.compile("1f\d+\w*|[<>/=]") # 定義正則規則
for fri_info in we_friend[1:]:
signature = fri_info['signature']
if signature:
sign_deal = signature.replace('\n', '').replace('\t', '').replace(' ', '')\
.replace("span", "").replace("class", "").replace("emoji", "")
sign = rule.sub("", sign_deal)
sign_li.append(sign)
複製代碼
pwd_path = os.path.abspath(os.path.dirname(os.getcwd()))
conf_path = os.path.join(pwd_path, 'conf/')
comment_txt = ''
back_img = plt.imread(conf_path + '/peiqi.jpg')
cloud = WordCloud(font_path=conf_path + '/simhei.ttf', # 如果有中文的話,這句代碼必須添加,否則會出現方框,不出現漢字
background_color="white", # 背景顏色
max_words=5000, # 詞雲顯示的最大詞數
mask=back_img, # 設置背景圖片
max_font_size=100, # 字體最大值
random_state=42,
width=360, height=591, margin=2, # 設置圖片默認的大小,可是若是使用背景圖片的話,保存的圖片大小將會按照其大小保存,margin爲詞語邊緣距離
)
for li in comment:
comment_txt += ' '.join(jieba.cut(li, cut_all=False))
wc = cloud.generate(comment_txt)
image_colors = ImageColorGenerator(back_img)
plt.figure("wordc")
plt.imshow(wc.recolor(color_func=image_colors))
wc.to_file(res_full + '好友個性簽名詞雲圖.png')
複製代碼
最初,只想作一個簡單的詞雲圖,可是看到這個詞雲圖中夢想、努力、專一、尊重、但願這個幾個詞之後,感受到個人好友生活態度仍是蠻積極向上的,就想不如再作一個簡單的情感分析,說幹就幹。
sentimentslist = []
for li in comment:
if len(li) > 0:
s = SnowNLP(li)
print(li, s.sentiments)
sentimentslist.append(s.sentiments)
fig1 = plt.figure("sentiment")
plt.hist(sentimentslist, bins=np.arange(0, 1, 0.02))
plt.savefig(res_full + '好友簽名情感分析')
plt.show()
複製代碼
從圖中能夠看出,正向情感要遠遠多於負向情感的數據,積極樂觀的人每每都在一個圈子,果真是物以類聚,人以羣分啊。
完整代碼以上傳Github,期待您的Star。