python3.6
环境:pycharm
代码中用到的包全部为2019.5.1之前的最新版本
有问题欢迎交流。
思路:通过微信个人号网页版接口ichat对微信数据进行处理(微信朋友圈没有接口),pyecharts对数据进行建表等操作,用Pillow包对头像进行处理。
结果:代码经测试无需更改任何人可以使用,登陆时用微信扫码方式。目前了解,对于2018年之后申请的微信号,腾讯已经关闭了微信网页版登陆权限,无法使用此代码。最终形成了性别比例,省份分布,前top10城市人数,微信头像拼接成一个图片。
扩展:(1)ichat有收发消息功能,这意味着可以做一个聊天机器人,发广告什么的需要用手吗?恩,如果你弄个百度AI的接口,我觉得对方能玩一年。(2)群发消息。粘贴复制的消息大家都看腻了,如果加上对方的名字等信息是不是更暖心呢?总体来说太局限了,暂时还没发现什么好玩的。看看以后能不能扩展吧。
附送运行结果和代码
import itchat, os, re, random, math
from pyecharts.charts import Page, Pie, Geo, Bar
from pyecharts import options as opts
from PIL import Image
def get_key_info(friends_info, key): # 获取想知道的好友信息组成列表,中间调用了get_friends_info(friends)
return list(map(lambda friend_info: friend_info.get(key), friends_info))
# lambda表示匿名函数,对friend_info执行:后面的操作输出的结果。map表示对friends_info每个元素执行其逗号前的操作
def get_friends_info(friends): # 获取想知道的信息。
friends_info = dict(
username=get_key_info(friends, 'UserName'), # 用户名
sex=get_key_info(friends, 'Sex'), # 性别
province=get_key_info(friends, 'Province'), # 省份
city=get_key_info(friends, 'City') # 城市
)
return friends_info
# 处理数据
def count_nums(new_list): # 对好友信息进行处理,比如:英文的省份不要
new_dict = {}
for i in new_list:
if bool(re.search('[a-z]|[A-Z]', i)): # 如果匹配到英文字母就跳出本次循环
continue
elif not new_dict.__contains__(i): # 判断字典中有没有这个信息,没有的话加上,有的话计数加一
new_dict[i] = 1
else:
new_dict[i] += 1
new_dict.pop('') # 去掉空的键
return new_dict
def analysis(friends):
friends_info = get_friends_info(friends)
# 男女性别比例
sex_list = friends_info['sex']
from collections import Counter
sex_dict = dict(Counter(sex_list)) # 性别计数
attr = ["未知", "男性", "女性"]
value = [sex_dict[0], sex_dict[1], sex_dict[2]]
page = Page() # 创建一个HTML网页
chart1 = ( # 创建性别分析图标
Pie()
.add("", [list(z) for z in zip(attr, value)])
.set_global_opts(title_opts=opts.TitleOpts(title="好友性别比例"))
.set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {c}"))
)
page.add(chart1) # 将图标加入HTML页面
# 中国省级分析
province_list = friends_info['province']
province_dict = count_nums(province_list)
attr, value = list(province_dict.keys()), list(province_dict.values())
chart2 = ( # 创建省份分析表
Geo()
.add_schema(maptype="china")
.add("所在省份", [list(z) for z in zip(attr, value)])
.set_series_opts(label_opts=opts.LabelOpts(is_show=False))
.set_global_opts(
visualmap_opts=opts.VisualMapOpts(),
title_opts=opts.TitleOpts(title="好友省级分布(中国地图)"),
)
)
page.add(chart2) # 加入到HTML页面
# 中国城市分析(取前10个人数最多的城市)
city_list = friends_info['city']
city_dict = count_nums(city_list)
top_ten_city = dict(sorted(city_dict.items(), key=lambda x: x[1], reverse=True)[0:10])
attr, value = list(top_ten_city.keys()), list(top_ten_city.values())
chart3 = ( # 创建城市分析表
Bar()
.add_xaxis(attr)
.add_yaxis('城市', value)
.set_global_opts(title_opts=opts.TitleOpts(title="好友城市分布Top10柱状图"))
)
page.add(chart3) #加入到HTML页面
page.render('analysisResult.html') # 生成HTML页面文件
def get_head_img(friends): # 获取好友头像信息
friends_info = get_friends_info(friends)
username = friends_info['username']
for i, uname in enumerate(username): # 把图片保存在当前文件夹下的headImgs文件夹下面并重命名
with open("headImgs/" + str(i) + ".png", "wb") as f:
img = itchat.get_head_img(uname)
f.write(img)
def create_img(): # 对头像进行拼接
x = 0
y = 0
imgs = os.listdir("headImgs") # 返回 headImgs 目录下的文件列表
random.shuffle(imgs) # 将文件列表随机排序
input_length = 360
input_width = 240
new_img = Image.new('RGBA', (input_width, input_length)) # 创建 长*宽 的图片用于填充各小图片
width = int(math.sqrt(input_length * input_width / len(imgs))) # 算出图片总面积然后除以图片数量,math.sqrt()开平方根计算每张小图片的宽高
num_line = int(input_width / width) # 每行图片数
for i in imgs: #对每一张图片逐个进行处理
try:
img = Image.open("headImgs/" + i)
except IOError:
print("第{}张图片为空".format(i))
else:
img = img.resize((width, width), Image.ANTIALIAS) # 缩小图片
new_img.paste(img, (x * width, y * width)) # 拼接图片,一行排满,换行拼接
x += 1
if x >= num_line:
x = 0
y += 1
new_img.save("mixedImg.png") # 存放图片
if __name__ == '__main__':
itchat.auto_login(hotReload=True) # 登陆
friends = itchat.get_friends(update=True) # 获取信息
analysis(friends) # 函数调用
curPath = os.getcwd() # 获取当前目录的绝对路径
tempPath = 'headImgs' # 存放头像图片的文件夹
targetPath = curPath + os.path.sep + tempPath # 存放头像图片文件夹的路径
if not os.path.exists(targetPath): # 创建 文件夹
os.makedirs(targetPath)
else:
print('路径已经存在!')
get_head_img(friends) # 函数调用
create_img() # 函数调用