用 Python 基于 pyecharts 对微信好友进行分析

参考博客在这里:https://blog.csdn.net/yaoyefengchen/article/details/79427475

Echarts 已经更新到了 ver.4 版本,原文用的是网页版的 Echarts,获取数据后还要在网页中修改数据生成图表,有大神基于 Echarts 写了一个 pyecharts 库,这样就可以一键获取数据生成图表了,代价就是多写几行代码,Python 3.6 测试通过。


1. 准备工作

准备库:
1. wxpy
2. pyecharts
3. echarts-countries-pypkg
4. jieba
5. pandas
6. numpy

都可以直接用 pip 命令进行安装,没有用到原文中的 scipy 和 wordcloud 库,因为我直接用了 pyecharts 里的 wordcloud,也没有用自定义图像。

自从 v0.3.2 开始,为了缩减项目本身的体积以及维持 pyecharts 项目的轻量化运行,pyecharts 将不再自带地图 js 文件。如用户需要用到地图图表,可自行安装对应的地图文件包。

echarts-countries-pypkg 就是我们需要的地图包,包含世界地图和 213 个国家,其中包括中国地图。


2. 获取数据

获取微信好友的性别、位置和个性签名等方法跟原文一样,所以我就不写了,主要是 pyecharts 库的使用。


3. 绘制图表

3.1 微信好友男女比例

Pie(饼图)

饼图主要用于表现不同类目的数据在总和中的占比。每个的弧度表示数据数量的比例。

Pie.add() 方法:

add(name, attr, value,
    radius=None,
    center=None,
    rosetype=None, **kwargs)
  • name -> str 图例名称
  • attr -> list 属性名称
  • value -> list 属性所对应的值
  • radius -> list 饼图的半径,数组的第一项是内半径,第二项是外半径,默认为 [0, 75],默认设置成百分比,相对于容器高宽中较小的一项的一半
  • center -> list 饼图的中心(圆心)坐标,数组的第一项是横坐标,第二项是纵坐标,默认为 [50, 50]
    默认设置成百分比,设置成百分比时第一项是相对于容器宽度,第二项是相对于容器高度
  • rosetype -> str 是否展示成南丁格尔图,通过半径区分数据大小,有 "radius""area" 两种模式。默认为 "radius"
    • radius:扇区圆心角展现数据的百分比,半径展现数据的大小
    • area:所有扇区圆心角相同,仅通过半径展现数据大小
from pyecharts import Pie

pie = Pie("微信好友男女比例", width=1200, height=400)
pie.add("", sex_dict.keys(), sex_dict.values(), is_label_show=True)
pie.render()

sex_dict 是第二步中获取的性别字典。
调用 render() 方法默认会在相同目录下生成一个 render.html 文件,打开就可以看到结果
微信好友男女比例

扫描二维码关注公众号,回复: 3047803 查看本文章

3.2 微信好友全国分布图

Map(地图)

地图主要用于地理区域数据的可视化。

Map.add() 方法:

add(name, attr, value,
    maptype='china',
    is_roam=True,
    is_map_symbol_show=True, **kwargs)
  • name -> str 图例名称
  • attr -> list 属性名称
  • value -> list 属性所对应的值
  • maptype -> str 地图类型
  • is_roam -> bool/str 是否开启鼠标缩放和平移漫游,默认为 True。如果只想要开启缩放或者平移,可以设置成 "scale" 或者 "move"。设置成 True 为都开启
  • is_map_symbol_show -> bool 是否显示地图标记红点,默认为 True
from pyecharts import Map

friends_map = Map("微信好友全国分布图", width=1200, height=600)
friends_map.add(
    "",
    province_dict.keys(),
    province_dict.values(),
    is_label_show=True,
    is_visualmap=True,
    visual_range=[0, max(province_dict.values())],
    visual_range_text=['少', '多'],
    visual_range_color=['#FFFF00', '#D6292B']    # [黄,红]由低到高
)
friends_map.render()

province_dict 就是获取的省份统计字典。
is_visualmap 设为 True 启用视觉映射组件。
visual_range 指定组件的允许的最小值与最大值。这里最大值设为省份数的最大值。
visual_range_text 两端文本。
visual_range_color 过渡颜色,这里设置为由黄到红,没有设为纯红,因为太亮眼了。

微信好友全国分布图

3.3 微信好友签名统计

WordCloud(词云图)
WordCloud.add() 方法:

add(name, attr, value,
    shape="circle",
    word_gap=20,
    word_size_range=None,
    rotate_step=45)
  • name -> str 图例名称
  • attr -> list 属性名称
  • value -> list 属性所对应的值
  • shape -> list 词云图轮廓,有 'circle', 'cardioid', 'diamond', 'triangle-forward', 'triangle', 'pentagon', 'star'可选
  • word_gap -> int 单词间隔,默认为 20。
  • word_size_range -> list 单词字体大小范围,默认为 [12, 60]。
  • rotate_step -> int 旋转单词角度,默认为 45
from pyecharts import WordCloud

words_cloud = WordCloud("微信好友个性签名词云", width=1200, height=600)
word_freq = {x[0]: x[1] for x in words_stat.head(100).values}
words_cloud.add(
    "",
    word_freq.keys(),
    word_freq.values(),
    shape="circle"
)
word_cloud.render()

word_stat 是统计的词频。
微信好友个性签名词云

3.4 在同一页面显示

Page:同一网页按顺序展示多图

from pyecharts import Page

page = Page("")
page.add(pie).add(friends_map).add(words_cloud)
page.render()

使用 add() 向 page 中添加之前生成的三个图。打开 render.html 文件就可以看到三个图表直接显示在一个网页中,十分方便查看。


4. 总结

pyecharts 官网上还有很多可用的图表,官方例程也十分简洁明了,而且已经支持 Django/Flask 等框架,可以部署在网页上,也正是我现在在做的。wxpy 还有很多功能没有被用到,多多发掘就会有更多有趣的应用产生。


5. 完整代码

代码基于原博进行了适当的修改

from wxpy import Bot
from pyecharts import Pie, Map, WordCloud, Page
import re
import jieba
import pandas as pd
import numpy

def write_txt_file(path, txt):
    """
    写入 txt 文本
    """
    with open(path, 'a', newline='') as f:
        f.write(txt)

def read_txt_file(path):
    '''
    读取 txt 文本
    '''
    with open(path, 'r', newline='') as f:
        return f.read()

def login():
    # 初始化机器人,扫码登录
    bot = Bot()

    # 获取所有好友
    my_friends = bot.friends()
    return my_friends

def get_sex_ratio(friends):
    """
    统计好友男性和女性的数量
    """
    sex_dict = {'男性': 0, '女性': 0}

    for friend in friends:
        if friend.sex == 1:
            sex_dict['男性'] += 1
        elif friend.sex == 2:
            sex_dict['女性'] += 1
    return sex_dict

def get_area_distribution(friends):
    """
    统计各省好友数量
    """
    province_dict = {
        '北京': 0, '上海': 0, '天津': 0, '重庆': 0, '河北': 0,
        '山西': 0, '吉林': 0, '辽宁': 0, '黑龙江': 0, '陕西': 0, 
        '甘肃': 0, '青海': 0, '山东': 0, '福建': 0, '浙江': 0, 
        '台湾': 0, '河南': 0, '湖北': 0, '湖南': 0, '江西': 0, 
        '江苏': 0, '安徽': 0, '广东': 0, '海南': 0, '四川': 0, 
        '贵州': 0, '云南': 0, '内蒙古': 0, '新疆': 0, '宁夏': 0, 
        '广西': 0, '西藏': 0, '香港': 0, '澳门': 0
    }

    for friend in friends:
        # 统计省份
        if friend.province in province_dict:
            province_dict[friend.province] += 1
    return province_dict

def get_signatures(friends):
    """
    统计签名
    """
    for friend in friends:
        # 对数据进行清洗,将标点符号等对词频统计造成影响的因素剔除
        pattern = re.compile(r'[一-龥]+')
        filterdata = re.findall(pattern, friend.signature)
        write_txt_file('signatures.txt', ''.join(filterdata))

    content = read_txt_file('signatures.txt')
    segment = jieba.lcut(content)
    words_df = pd.DataFrame({'segment': segment})

    stopwords = pd.read_csv(
        'chineseStopWords.txt',
        index_col=False,
        quoting=3,
        sep=' ',
        names=['stopword']
    )
    words_df = words_df[~words_df.segment.isin(stopwords.stopword)]

    words_stat = words_df.groupby(by=['segment'])['segment'].agg({"计数": numpy.size})
    words_stat = words_stat.reset_index().sort_values(by=['计数'], ascending=False)

    return words_stat

def show_page(sex_dict, province_dict, words_stat):
    """
    将图表渲染为一个 html 页面
    """
    pie = Pie("微信好友男女比例", width=1200, height=400)
    pie.add("", sex_dict.keys(), sex_dict.values(), is_label_show=True)

    friends_map = Map("微信好友全国分布图", width=1200, height=600)
    friends_map.add(
        "",
        province_dict.keys(),
        province_dict.values(),
        is_label_show=True,
        is_visualmap=True,
        visual_range=[0, max(province_dict.values())],
        visual_range_text=['少', '多'],
        visual_range_color=['#FFFF00', '#D6292B']    # [黄,红]由低到高
    )

    words_cloud = WordCloud("微信好友个性签名词云", width=1200, height=600)
    word_freq = {x[0]: x[1] for x in words_stat.head(100).values}
    words_cloud.add(
        "",
        word_freq.keys(),
        word_freq.values(),
        shape="circle"
    )

    # 使用 Page,将图表添加至一个页面
    page = Page("")
    page.add(pie).add(friends_map).add(words_cloud)
    page.render()

if __name__ == '__main__':
    friends = login()
    sex_dict = get_sex_ratio(friends)
    province_dict = get_area_distribution(friends)
    words_stat = get_signatures(friends)
    show_page(sex_dict, province_dict, words_stat)

猜你喜欢

转载自blog.csdn.net/qq_20084101/article/details/81227963