Python数据分析朋友圈信息

此文章基于Pyhon3.0以上版本对微信好友进行数据分析,这里选择的维度主要有以下几个:性别(Sex)、头像(HeadImg)、个人签名(Signature)和位置(Location),主要采用图表和词云的方式来呈现效果,其中,对于签名这块文本信息会采用jieba模块的词频分析和snownlp模块的情感分析两种方法。由于本文中用到的大多数模块都是第三方模块,故在正式开始本文章前,先简单介绍下使用到的主要的第三方模块。

第三方模块:

  • itchat:微信网页版接口封装的Python版本,可用来获取微信好友信息;
  • jieba:结巴分词的Python版本,可用以对文本信息进行分词处理;
  • matplotlib:Python的图标绘制模块,可用以绘制柱形图、饼图等
  • snownlp:Python的中文分词模块,可用以对文本信息进行情感分析
  • PIL:PIL仅支持到Python2.7,适用于Python3以上的兼容版本名为PIllow,同样是Python的图像处理模块,可用以对图片进行处理
  • numpy:Python的数值计算模块,可配合 wordcloud 模块使用。
  • wordcloud: Python 的词云模块,可用以绘制词云图片。

安装question:

PIL目前只支持python2.x版本,不支持python3.x。

解决办法:``

Pillow是PIL的一个派生分支,但如今已经发展成为比PIL本身更具活力的图像处理库。给Python安装Pillow非常简单,使用一行代码进行pip安装即可。

pip install Pillow

安装完成后,使用from PIL import Image就可以使用Pillow模块了

如何获取微信好友数据

分析微信好友数据的前提就是获得好友信息,通过使用itchat模块,你会发现其实并不难实现。

itchat.auto_login()
friends = itchat.get_friends(update=True)

通过auto_login()命令可以在登陆的时候使用命令行显示二维码,可加参数enableCmdQR来设置二维码背景颜色,添加参数hotReload=True将自动登录,itchat.get_friends(update=True)表示获取微信好友列表的 json 数据,以字典形式返回每个好友信息,如果设置update=True将从服务器刷新列表。

分析好友性别比例

分析好友性别,首先就得获得所有好友的性别信息,需要将好友信息的Sex字段取出来,因此我们使用了lambda匿名函数器将sex选择出来,然后使用collections.Counter分别统计Male、Female和Unknow的数目,再使用item转化为可遍历的元组,之后将此三个数值组装到一个列表中,即可用matplotlib模块绘制出饼图,关键代码如下:

def analySex(friends):
    total = len(friends[1:])#统计好友数量
    # 将friends中的Sex信息抽取出来,map返回的是迭代器,转化为list格式
    sexs=list(map(lambda x:x['Sex'],friends[1:]))
    # item返回(键,值)元组,第一维为键,第二维为值,即个数
    # 取性别个数变为列表
    counts=list(map(lambda x:x[1],collections.Counter(sexs).items()))
    lables=['Unknow','Male','Female']# 设置标签
    colors=['red','yellowgreen','lightskyblue'] # 设置标签颜色
    plt.figure(figsize=(8,5),dpi=80)
    # 设置为仅显示一个分区,不设置的话,图可能是椭圆的
    plt.axes(aspect=1)
    plt.pie(counts,#性别统计结果
            labels=lables,#性别展示标签
            colors=colors,#饼图展示颜色
            labeldistance=1.1,#标签距离圆点距离
            autopct='%3.1f%%',#饼图区域文本格式
            shadow=False,#饼图是否显示阴影
            startangle=90,#饼图起始角度
            pctdistance=0.6#饼图区域文本距离圆点距离
    )
    # 图例显示
    plt.legend(loc='upper right',)
    plt.title(u'%s的%d位微信好友性别组成' %(friends[0]['NickName'],total),fontproperties=font_set)
    plt.show()

稍微补充一下,在微信性别字段中的取值分别有Unknow,Male,Female三种,其中对应的数值分别是0、1、2接着就如上面所述的一致,将数据传递给matplotlib绘制即可,这三种不同取值各自所占的比例将会由matplotlib计算得出,效果如下:
在这里插入图片描述

分析好友地址分布

分析好友位置,需要我们提取Province和City字段,在此之前我曾经利用pd.DataFrame(friends)查看城市的数据段,发现一共有五十来个城市,于是我估量做出来的柱形图或者饼图铁定很难看,所以我们可以选择将其存储到本地‘location.csv’文件中,再统计各地区的好友数量将其存储到’location_analysis.xls’。最后利用BDP个人版制作出可视化地图,看起来还是勉勉强强过关的,关键代码如下:

扫描二维码关注公众号,回复: 4544441 查看本文章
def analyloc(friends):
    #用来记录对应省份,城市的人数
    freqs = {}
    headers = ['NickName', 'Province', 'City']
    #创建csv文件
    with open('location.csv', 'w', encoding='utf-8', newline='', ) as csvFile:
        # 调用DictWriter方法,其中headers指定字典的key值
        writer = csv.DictWriter(csvFile, headers)
        writer.writeheader() #  writeheader()实现添加文件头(数据名)
        #循环遍历微信好友
        # 设置列名NickName、Province、City并添加其中对应的信息
        for friend in friends[1:]:
            row = {}
            row['NickName'] = friend['NickName']
            row['Province'] = friend['Province']
            row['City'] = friend['City']
            if (friend['Province'] != None): # 统计对应城市数目
                if (friend['Province'] not in freqs):
                    freqs[friend['Province']] = 1
                else:
                    freqs[friend['Province']] += 1  
            writer.writerow(row)#写入列所对应的信息
    key_list = list(freqs.keys())#城市名或者省份名
    value_list = list(freqs.values()) #对应数量
    book = xlwt.Workbook(encoding='utf-8')#设置编码形式为utf-8
    sheet = book.add_sheet('sheet1') #添加工作表
    # Province中的'0-行, 0-列'即指定表中的单元
    sheet.write(0, 0, 'Province')  
    sheet.write(0, 1, 'Num')
    for i in range(len(freqs)): #写入工作表
        sheet.write(i + 1, 0, key_list[i])
        sheet.write(i + 1, 1, value_list[i])
    book.save('location_analysis.xls') #保存为location_analysis.xls

接下来使用BDP报表工具点击下方“数据源” ,添加数据“excel”,上传’location_analysis.xls’——新建图表——普通图表、仪表盘示例、微信运营分析——维度:province,数值:num——右侧,图表类型:地图即可。

在这里插入图片描述

下面就是BDP生成的微信好友位置分布图,这也反映出我的好友来自五湖四海,O(∩_∩)O哈哈~

在这里插入图片描述

好友个性签名文本情感及词云的制作

先获取好友列表中的个人签名信息,这里我们会对个人签名进行两种处理方式,第一种是使用结巴分词进行分词后生成词云,第二种是使用SnowNLP模块分析好友签名的感情倾向。以下是生成词云的关键代码:

def analySignature(friends):
    signatures=''
    emotions=[]
    pattern=re.compile("1f\d.+")
    for friend in friends:
        signature=friend['Signature']
        if(signature!=None):
            # 将个性签名中可能包含的表情及符号替换
            signature=signature.strip().replace('span','').replace('class','').replace('emoji','')
            #将个人签名中匹配到的数字替换为空字符串
            signature=re.sub(r'1f(\d.+)','',signature)
            if(len(signature)>0): #进行情绪分析
                nlp=SnowNLP(signature)
                #添加每段个人签名经情感分析返回后的情感系数的数据
                emotions.append(nlp.sentiments)
                signatures+=' '.join(jieba.analyse.extract_tags(signature,5)) #关键字提取
    # 通过中文分词工具 jieba 将文本分词后写入文件
    with  open('signatures.txt','wt',encoding='utf-8') as file:
        file.write(signatures)

    #生成词云图
    back_coloring=np.array(Image.open('love.jpg'))
    #设置词云图
    wordcloud=WordCloud(
        collocations=False,#是否包括两个词的搭配
        font_path='simfang.ttf',#字体设置路径
        background_color='white',#背景颜色
        max_words=1200,# 词云显示的最大词数
        mask=back_coloring,#设置词云形状
        max_font_size=30,#字体最大值
        random_state=30,#随机状态数
        width=960,#输出宽度
        height=720,#输出高度
        margin=2#外边距
        )
    # 根据文本生成词云, 可以用generate输入全部文本(中文不好分词),
    # 也可以我们计算好词频后使用generate_from_frequencies函数
    wordcloud.generate(signatures)
    plt.imshow(wordcloud)#绘制二维图
    plt.axis("off") # 去掉坐标轴
    plt.show()# 绘制词云
    wordcloud.to_file('signatures.jpg')# 保存图片

这里将展示情感分析的关键代码:

 #根据情绪的得分,绘制一个柱状图
    count_good=len(list(filter(lambda x:x>0.66,emotions)))#只过滤出情感系数大于0.66的数字
    count_normal=len(list(filter(lambda x:x>=0.33 and x<=0.66,emotions)))
    count_bad=len(list(filter(lambda x:x<0.33,emotions)))
    labels=[u'负面消极',u'中性',u'正面积极']
    values=(count_bad,count_normal,count_good)
    plt.rcParams['font.sans-serif']=['simHei']#设置字体,以免出现乱码
    plt.rcParams['axes.unicode_minus']=False#用来正确显示负号
    plt.xlabel(u'情感判断')#x轴出现的文本
    plt.ylabel(u'频数')#y轴出现的文本
    plt.xticks(range(3),labels)#为x轴刻度设置标签
    plt.legend(loc='upper right',)#图例显示在右上角
    plt.bar(range(3),values,color='rgb')#设置柱体的位置分布和大小,以及颜色格式。
    plt.title(u'%s的微信好友签名信息情感分析'% friends[0]['NickName'],fontproperties=font_set)
    plt.show()

在词云图中,我们可以发现出现频率较多的关键词有:相信、美好、快乐、奋斗等相对正面积极向上的词汇,这也说明接下来的情感分析中正面积极的将会占较大比例。
在这里插入图片描述
果然,我的智商一向不会让我失望。
在这里插入图片描述

获取好友头像并组合成自定义头像

很明显,首先我们就得获取好友的头像,然后利用Pillow模块的拼接方法进行绘图制作,这是一个相当有意思的制作过程,因为在这里我们可以用自定义图片作为主图片的最终框架,关键代码如下:

def Splicing(friends):
    k = 0
    for i in friends:
        img = itchat.get_head_img(userName=i["UserName"]) #获取头像
        #对每张头像进行略微简单的命名
        fileImage = open(r'HeadImg' + "/" + str(k) + ".jpg", 'wb')
        fileImage.write(img)
        fileImage.close()
        k += 1 #计数,方便命名,同时递增
    img = Image.open('im.bmp') #头像最终组合成的图片样例
    # 获取图像的灰度值范围
    w = img.size[0]
    h = img.size[1]
    r = math.ceil(1040 / w)    #最大取值
    # 重新设定大小,设定ANTIALIAS,即抗锯齿
    img = img.resize((int(w * r / 100) * 100, int(h * r / 100) * 100), Image.ANTIALIAS)
    s = os.listdir(r'HeadImg')
    c = len(s)
    w = img.size[0]
    h = img.size[1]
    newim = Image.new('RGB', (w, h),(255,255,255)) #根据规模创建图片
    k = 0
    x = 0
    y = 0
    for i in range(0, w, 40):
        for j in range(0, h, 40):
            p = img.getpixel((i, j))[2] #获取像素值
            if(p != 255): #如果不等于白色,进行下面操作
                try:
                    im = Image.open(r'HeadImg' + "/" + str(k) + ".jpg")
                except:
                    if k == c - 1:
                        k = 0
                    else:
                        k += 1
                finally:
                    im = Image.open(r'HeadImg' + "/" + str(k) + ".jpg")
                    im = im.resize((40, 40), Image.ANTIALIAS)#设置每张头像图片尺寸为40*40px
                    newim.paste(im, (i, j)) #图片粘贴的位置
                    if k == c - 1:
                        k = 0
                    else:
                        k += 1
    newim.save(r'HeadImg' + "/" + "all.bmp")    #保存图片
    itchat.send_image(r'HeadImg' + "/" + "all.bmp", 'filehelper')#向文件助手发送该图片

当当当!展示下效果,是不是很骚O(∩_∩)O

在这里插入图片描述

交互界面

最后,我们可以使用Python中的内置图形界面tkinter模块,简单设置下基础界面,通过确定按钮的点击事件,使得调用函数的过程更加形象,由于该窗口过于简单,我就不一一介绍其中的代码了,关键代码如下:

#搭建界面
root = Tk()#创建窗口
root.title("Wechat爬好友数据")#补充窗口标题
root.geometry("500x350")#设置窗口大小
root.resizable(False, False)#固定窗口大小
#标签控件
label=Label(root,text="      昵称:",font=('宋体',12))
label.place(x=60,y=37)
#显示框
text1=Text(root,font=('宋体',15),height=1,width=20)
text1.place(x=150,y=33)
text1.insert(1.0,friends[0]['NickName'])
#按钮
button1=Button(root,text="性别分析",font=('微软雅黑',10),command=analySex)
button1.place(x=50,y=90)
button2=Button(root,text="地理分布",font=('微软雅黑',10),command=analyloc)
button2.place(x=150,y=90)
button3=Button(root,text="词云图",font=('微软雅黑',10),command=analySignature)
button3.place(x=240,y=90)
button4=Button(root,text="情感分析",font=('微软雅黑',10),command=analyemotion)
button4.place(x=320,y=90)
button5=Button(root,text="拼接头像",font=('微软雅黑',10),command=Splicing)
button5.place(x=420,y=90)
button1=Button(root,text="   退出  ",font=('微软雅黑',14),command=root.quit)
button1.place(x=200,y=150)
root.mainloop()##让根窗口进入事件循环

看起来还是勉勉强强可以接受的!
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_38642610/article/details/85009713