完整源码可在公众号:「01 二进制」后台回复:「公众号数据分析」获取
1. 前言
在同学的影响下,我在 18 年 9 月注册了一个公众号「01 二进制」,因为种种原因(其实就是懒)直到 11 月 11 日才在这个公众号上发布了第一篇文章。到写这篇文的时候,我已经发布过 21 篇文章,用户也只有 86 人,这不禁引发了我深深的思考。为啥我的公号没有用户?
为此我还特地请教了我的好友 🐔 哥,他告诉我,文笔是一方面,另一方面还要能抓住热点,说完便给我发了一份某知名公众号的相关数据,让我给安排安排。
这不,一分析才发现原来想让公众号有阅读量也是要讲究套路的,接下来就让我们以一个 coder 的角度去分析下究竟是哪些套路吧。
2. 分析目的
笔者在本项目中的分析目的主要有 3 个:
(1)对某知名公众号内容运营方面的若干分析,主要是对发文量、点赞量、发文时间等方面的描述性分析;
(2)通过对标题的分析,来说明什么样标题更受人喜欢;
(3)将冗杂无序的结构化数据和非结构化数据进行可视化,展现数据之美。
3. 实验环境
工欲善其事,必先利其器,在开始分析之前,我先说明此次分析所处的实验环境,以免出现异常:
- MacOS 10.14.3
- Python 3.6.8(Anaconda)
- Visual Studio Code(开发)
- Jupyter Notebook(调试环境)
使用的包有:
- pkuseg(分词)
- pyecharts(绘图)
- numpy(数学计算)
- pandas(数据计算)
4. 数据获取及预览
4.1 数据获取
本次数据集是通过网络爬虫爬取某公众号的所以文章整理而成,该部分不进行阐述,需要数据集可以直接下载源码查看或者在公众号:「01 二进制」后台回复:「公众号数据集」获取。
4.2 数据预览
在该项目中,我使用了 Pandas 进行数据的读取和预览,Pandas 在数据科学中使用非常广泛,有兴趣的小伙伴可以去搜索相关资料了解下。
数据预览代码如下:
import pandas as pd
# 读取数据集
df=pd.read_excel('data/data.xlsx')
# 显示前五行数据
df.head()
此次的数据集长下面这样 👇:
我统计了下,截至 2019 年 1 月 22 日,该公众号总共发表文章 1111 篇(对单身 🐶 还真是一个友好的数字呢)。
5. 描述性分析
该部分中,笔者将会对该数据集中主要的数值型数据进行描述性的统计分析,属于较为常规的数据分析,能揭示出一些问题。可视化工具采用的是pyecharts,官网地址:http://pyecharts.org/#/,推荐使用他的原因是因为他的图表好看(颜即正义)。
5.1 文章来源
单靠一个人的力量想要让公众号保持每日一文的活跃度很难。所以,很多公众号都会适时的转载一些别人写的比较好的文章。但如果转载文章过多,原创性就大大降低了,那么比例要多少比较好呢?我们来看看该知名公众号的转载文章数量和原创文章数量吧:
# 获取转载文章
df_copy = df[df['原文链接'].str.len() > 5]
print('转载文章数量为:'+str(len(df_copy)))
print('原创文章数量为:'+str(len(df)-len(df_copy)))
在该数据集中,只要原文链接这一栏里有数据的则默认为转载,没有数据的默认为原创,输出的结果为:
转载文章数量为:249
原创文章数量为:862
粗略计算下比例大约为3.5:1
5.2 他到底有多火
从文章开始我就在说这个数据集是某知名公众号的数据集,那么到底有多知名呢?接下来我们从发文数量、点赞数量和平均每篇文章的点赞数量入手来一探究竟。
其实这个部分的思路不难:只需要创建一个 5 行 4 列(表示 5 年,4 个季度)的矩阵,获取到时间所在的年份和季度后再在相应位置上加 1:
# 获取文章数随季度变化的矩阵
def getPostJiDu(df):
# 生成一个5行4列全为0的矩阵
list_jidu = [[0]*4 for i in range(5)]
for articleTime in df['发文时间']:
# 获取日期
date = str(articleTime).split(' ')[0]
# 获取所在年份
year = getYear(date)
# 获取所在季度
jidu = getJiDu(date)
list_jidu[year-2015][jidu-1] += 1
return list_jidu
然后在利用pyecharts将图标画出来即可:
# 画出发文数量随季度变化的走势图
def drawPostJiDu(df):
# 获取文章季度矩阵
res_list = getPostJiDu(df)
# 构造标题列表
attr = []
for year in range(len(res_list)):
for month in range(len(res_list[year])):
attr.append("{}年第{}季度".format(str(year+2015),str(month+1)))
# 构造值列表
v1 = reduce(operator.add, res_list)
# 去掉无用值
attr = attr[2:-3]
v1 = v1[2:-3]
line = Line("发文数量变化走势图", width=1500, height=500)
line.add("某知名公众号", attr, v1, is_stack=True,
is_label_show=True, is_smooth=True, is_fill=True, xaxis_name='季度', yaxis_name='发文数',xaxis_rotate=30)
return line
这里提一下,因为该公众号 2015 年第 1、2 季度和 2019 年 2、3、4 季度均没有数据,所以需要执行一步去掉无用值的操作。
以此类推我们也可以得到点赞数量随时间变化的走势图:
下面是平均每篇文章点赞数量的变化。
不得不说,这个公众号的流量真的不容小觑,平均一篇文章能有 1w+的点赞量(还不算阅读量),难怪广告商都排队买她家的广告位,据说有的广告商甚至开出了 30w 的广告费!(啥时候我的文章也能有这么多流量啊 😢)
5.3 会不会是标题党
说实话,笔者在做分析的时候,看到上面的数据异常震惊,他每天到底发的是什么样的文章才能有这么庞大的流量啊。
高中语文老师经常跟我们提起,一个好的文章标题可以给你的文章加分不少。想到这我就开始怀疑这家伙会不会是一个标题党?又或是它的标题真的那么吸引人?实践是检验整理的唯一标准。来来来,收起笑容,我们来分析下。
5.3.1 什么样的文章标题更讨喜
这一部分我们的思路如下:获取到文章标题,然后进行分词、停用词过滤、统计词频,生成词云。这些都是上篇文章介绍过的,如果不清楚,移步《李鬼见李逵——我用翟天临的论文做了分析》,这里直接上代码:
# 选择文章标题并分析
def chooseMostPop50Titles(df):
texts=[]
for title in list(df['标题']):
# 防止出现没有标题的文章
if len(str(title))>3:
if str(title) not in ['分享图片']:
# 分词、去掉停用词
text=cleanWord(str(title))
texts.append(text)
# 将二维数组变成一维数组
title_cuts=reduce(operator.add, texts)
# 统计每个词的词频
counter = Counter(title_cuts)
# 选出词频最高的50个
counter=counter.most_common(50)
# 输出词频最高的50个单词
pprint.pprint(counter)
name = []
value = []
for count in counter:
name.append(count[0])
value.append(count[1])
return drawWordCloud(name,value)
# 数据可视化(生成词云)
def drawWordCloud(name, value):
wordcloud = WordCloud(width=800, height=400)
wordcloud.add("标题词云图", name, value, word_size_range=[
20, 100], rotate_step=20)
return wordcloud
考虑到篇幅的问题,词频统计的结果我就不放出来了,这里直接放出词云图:
看到这张词云图,大致就能猜到该公众号面向的主要群体是哪一类人了。有兴趣的可以在评论区留言说说你对这张词云图的想法。
5.3.2 标题多长比较好
标题能抓住痛点自然是好事,但是和长度有没有关系呢?(这个部分很简单,就是归类下长度,所以直接放代码了)
# 画出标题长度和点赞数之间的关系
def drawTitleLenAndFavourite(df):
v1 = [0]*6
for i in range(len(df['标题'])):
title_len = len(str(df['标题'][i]))
if title_len >= 5 and title_len <= 8:
v1[0] += df['点赞'][i]
elif title_len >= 9 and title_len <= 12:
v1[1] += df['点赞'][i]
elif title_len >= 13 and title_len <= 16:
v1[2] += df['点赞'][i]
elif title_len >= 17 and title_len <= 20:
v1[3] += df['点赞'][i]
elif title_len >= 20 and title_len <= 24:
v1[4] += df['点赞'][i]
elif title_len >= 25:
v1[5] += df['点赞'][i]
attr = ['5-8', '9-12', '13-16', '17-20', '21-24', '24+']
bar = Bar("标题长度和点赞数之间的关系", title_pos='center')
bar.add("", attr, v1, is_label_show=True)
return bar
可视化结果:
现在想想,高中语文老师说的标题不宜过长,也不宜过短,13-16 字之间最适宜原来不是忽悠我啊。
5.4 什么时候发文章比较好
每个人看文章的时间都不确定,但是大多数人的空闲时间还是差不多的,所以到这就有人会问了什么时候推送文章会比较好呢?我们先来看看这个公众号是怎么安排的。
5.4.1 发文数量和所在时间段的关系
粗略的浏览了下数据发现大多都是在晚上,所以这里我觉得采用饼状图来可视化二者之间的关系比较好(其实就是想顺便换个图表试试)
# 画出发文数量和所在小时之间的饼状关系图
def drawPostHour(df):
# 获取发文时间
list_hour = getPostHour(df)
array = np.array(list_hour)
# 获取发文时间最多的5个时间段
attr = list(sorted(np.argsort(array)[-5:]))
attr = ["{}时".format(i) for i in attr]
# 获取发文时间最多的5个时间的数量
v1 = list(array[sorted(np.argsort(array)[-5:])])
pie = Pie("发文时间分布图")
pie.add("", attr, v1, is_label_show=True)
return pie
在上述代码中,我们用getPostHour()
这个函数来生成一个集合,思路和上面类似,先生成一个全为 0 的列表,在时间内的加一就可以了。下面是生成的饼图:
可以看到该公众号大多数文章都是在晚上 10 点、11 点左右推送的,细想一下确实也是。大多数上班族在睡觉之前也就是这个时间段躺在床上刷手机,久而久之都让用户养成每天睡觉前必看一篇文章的习惯了,不得不说这种用户黏性是真的强啊!
5.4.2 用户点赞量如何
公众号推文给用户,那用户对文章的反应怎么样呢?我们来看看用户点赞随发文时间的柱状图:
代码的思路和之前的一致,这里就不放出来了,总的来说,这个公众号的点赞量还是很可观的。
6. 结语
通过上述几个分析,我觉得如果想让公众号有更多的读者和阅读量上一个台阶可以从下面 2 个角度去考虑:
- 要起一个好的标题,这个标题一定要符合你面向群体的喜好,而且不能太长
- 思考一下你面向群体的空闲时间,在空闲时间内推送文章,逐渐让用户对公众号产生黏性
此外,本文是基础的探索性质的数据分析文,不是数据分析报告,重在启迪思路,授人以渔,而且受限于数据规模,得出结论不是本文的目的,对结果的分析分散在各个部分,“文末结论控”不喜勿喷。