爬虫专题程序员大数据,机器学习,人工智能

乱炖“简书交友”数据之代码(1)

2018-06-13  本文已影响174人  古柳_Deserts_X

上一篇文章乱炖数据之2700余篇“简书交友”专题文章数据的花式玩法发布后,不少人想学习下代码,由于此前不曾在GitHub上开源过,流程还不熟悉,再者本项目中很多尝试性的代码,异常杂乱,因而没有立马公开。在经过删减和整理后,将继续更新出来。

本文主要涉及一些结构化数据的分析,文本数据如词频统计、词云图等等。暂且跳过爬虫部分。 代码见于 GitHub - DesertsX / JianShuJiaoYou,后续LDA主题模型、word2vec词向量、文章照片爬取、人脸识别及颜值打分和照片墙等等更新后也会开源在此项目,欢迎star与指正。

另外先预告下,之后打算开个“Kaggle Kernel 学习系列”,GitHub - DesertsX / Kaggle-Kernel-Learning,主要是翻译和学习下kaggle上优秀的kernels。其中第一篇非常粗糙,还没润色、修改排版布局的notebook可供浏览下,也欢迎关注、star和提供宝贵建议:
https://desertsx.github.io/2018/06/09/1_1_Start_Here-A_Gentle_Introduction/
https://desertsx.github.io/2018/06/09/kaggle-Kernel-01/

结构化数据

文章配图数

读取数据

import pandas as pd
df12 = pd.read_csv('JianShuJiaoYou-All-Data.csv', encoding='utf-8')
df12.head(2)

结果如下:

Page    Num Author  Author_Url  Title   Time    Read    Comment Like    Abstract    Artical_Url Image_Url   Artical_Content
0   1   0   刘秀玲 https://www.jianshu.com/u/470f33ea0c92  我要嫁这样的你 2016-07-25T12:16:39+08:00   109763  4508    5333    你不用太高,比穿三五厘米跟鞋的我看起来不矮就行。我不是小鸟依人的型,累了或者想哭的时候,我愿...   https://www.jianshu.com/p/8de3d395734f  ['//upload-images.jianshu.io/upload_images/125...   你不用太高,比穿三五厘米跟鞋的我看起来不矮就行。我不是小鸟依人的型,累了或者想哭的时候,我愿...
1   1   1   道长是名思维贩子    https://www.jianshu.com/u/92eb338437ee  如果你喜欢一个人,说些什么话让对方也喜欢你呢  2017-10-29T11:42:34+08:00   69260   497 3693    NaN https://www.jianshu.com/p/373d67f7cbce  ['//upload-images.jianshu.io/upload_images/299...   你现在有没有喜欢一个人?

新增Images_Num一列记录每篇文章配图数,但发现数字异常,Image_Url中的每一元素是字符串而非列表。

def images_num(imageslist):
    return len(imageslist)
df12['Images_Num'] = df12.Image_Url.apply(images_num)
df12.head(1)
df12.Images_Num.hist();
output_4_0.png

将字符串转化成 list 格式

eval()函数:可以将 list, tuple, dict 与 string 相互转化

实例:

a = "[[1,2], [3,4], [5,6], [7,8], [9,0]]"
print(a)
print(type(a))
b = eval(a)
print(b)
print(type(b))

输出结果:

[[1,2], [3,4], [5,6], [7,8], [9,0]]
<class 'str'>
[[1, 2], [3, 4], [5, 6], [7, 8], [9, 0]]
<class 'list'>

统计每篇文章配图数的正确方式

def images_num(imageslist):
    return len(eval(imageslist))
df12['Images_Num'] = df12.Image_Url.apply(images_num)
df12.head(1)

分布情况

df12.Images_Num.value_counts()

直方图
分布情况一目了然,文章配图数最多的高达80+。

df12.Images_Num.hist();
output_12_0.png

文章长度 / 字数

粗略统计下每篇文章的长度

def artical_length(artical_content):
    return len(artical_content)
df12['Artical_Length'] = df12.Artical_Content.apply(artical_length)
df12.head(1)
df12.Artical_Length.hist();
output_15_0.png

字数与配图数

看看文章篇幅和配图数之间是否存在某种关系。
seaborn.jointplot

import seaborn as sns
sns.jointplot(x="Artical_Length" , y = "Images_Num" ,data = df12);

改个参数看看

sns.jointplot(x="Artical_Length" , y = "Images_Num" ,data = df12, kind="hex");

评论数与点赞数

由皮尔逊相关系数为0.58可知,评论数与点赞数有一定的线性相关性。

sns_joinplot = sns.jointplot(x="Like" , y = "Comment" ,data = df12);
sns_joinplot.savefig('seaborn_Like_Comment_joinplot.png')

阅读量、评论数与点赞数

python3d画图mpl_toolkits.mplot3d
Matplotlib 绘图教程(3D)

from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
%matplotlib inline

plt.figure(figsize=(12, 7))
ax1 = plt.subplot(111,projection='3d')
x,y,z = df12['Read'],df12['Comment'],df12['Like']
ax1.scatter(x, y, z, s=15)
ax1.set_title('Read-Commnet-Like')
ax1.set_zlabel('Like')
ax1.set_ylabel('Comment')
ax1.set_xlabel('Read')
#plt.show()
output_25_1.png

多变量

看看阅读量、评论数、点赞数、文章篇幅与配图数五个变量之间的相关关系。

Pairplot图

seaborn.pairplot

import matplotlib.pyplot as plt
data = df12[["Read", "Comment", "Like", "Artical_Length","Images_Num"]]
#plt.figure(figsize=(6,4))
g = sns.pairplot(data, palette="husl");
g.savefig('seaborn_pairplot.png')

Heatmap图

seaborn-heatmap

sns.heatmap(data=data.corr(), annot=True, linewidths=0, vmin=-0.2, cmap='RdBu_r');
sns.heatmap( data=data.corr(), annot=True, linewidths=0, vmin=-0.2, cmap='YlGnBu');

文章发布时间

Time列分别提取年份、月份、天、小时等等数据。

def split_time_ymd(timestamp):
    ymd = timestamp.split('T')[0]
    return ymd

def split_time_year(timestamp):
    ymd = timestamp.split('T')[0]
    year = ymd.split('-')[0]
    return year

def split_time_month(timestamp):
    ymd = timestamp.split('T')[0]
    month = ymd.split('-')[1]
    return month

def split_time_day(timestamp):
    ymd = timestamp.split('T')[0]
    day = ymd.split('-')[-1]
    return day

def split_time_hour(timestamp):
    timestamp = timestamp.split('T')[1]
    hour = timestamp[:2]
    return hour

df12['YMD'] = df12.Time.apply(split_time_ymd)
df12['Year'] = df12.Time.apply(split_time_year)
df12['Month'] = df12.Time.apply(split_time_month)
df12['Day'] = df12.Time.apply(split_time_day)
df12['Hour'] = df12.Time.apply(split_time_hour)
df12.head(2)

发文年份

可以和另一专题“今日看点”及一篇旧文里的数据比较:简书=鸡汤?爬取简书今日看点:1916篇热门文章可视化

df12.Year.value_counts()
    2018    1992
    2017     718
    2016       6
    2015       2
    Name: Year, dtype: int64
import matplotlib.pyplot as plt
%matplotlib inline
df12.Year.hist();

发文月份

df12.Month.value_counts()
    04    644
    03    471
    05    444
    02    251
    11    237
    08    205
    01    188
    12     93
    10     93
    09     82
    07      8
    06      2
    Name: Month, dtype: int64
df12.Month.hist();

发文日期

df12.Day.hist();

发文小时

df12.Hour.hist();

ECharts美颜一下:发文小时

上述绘制的发布时间的相关图表都不够美观,于是翻出压箱底的又一篇旧文:图表太丑怎么破,ECharts神器带你飞!

直接套用ECharts图表模板,改下数据和标题等参数就行了,代码参见:简书交友”专题文章之24小时分布情

更多图表见于:ECharts3官网的个人主页

年度月份分布情况

df12.groupby(['Year','Month']).Month.count()
    Year  Month
    2015  04         1
          09         1
    2016  07         2
          08         1
          10         1
          12         2
    2017  01         1
          02         3
          04         1
          06         2
          07         6
          08       204
          09        81
          10        92
          11       237
          12        91
    2018  01       187
          02       248
          03       471
          04       642
          05       444
    Name: Month, dtype: int64

ECharts美颜一下:年度月份

图表太丑怎么破,ECharts神器带你飞!
ECharts3官网的个人主页

echarts_bar_year_month.js里代码复制到该链接后刷新即可:“简书交友”专题文章之年度月份分布情况

文本挖掘

相关旧文一篇:2017,那些出现在日记中的人:简单的文本挖掘

读取数据

import warnings
warnings.filterwarnings("ignore")
import jieba
import numpy as np
import codecs
import pandas as pd  
import matplotlib.pyplot as plt
%matplotlib inline
import matplotlib
matplotlib.rcParams['figure.figsize'] = (10.0, 5.0)
from wordcloud import WordCloud
# https://github.com/amueller/word_cloud/
# conda install -c conda-forge wordcloud

文章内容转化成 list 格式

这段情话还不错的样子,一定是个可爱漂亮的小姐姐写的吧,逃...

content = df12.Artical_Content.values.tolist()
print(len(content), '\n', content[-1])
2718 
我攒了一被子的情话,想要说给你听最近有种很杂碎的感觉,嗯...如果用比喻修辞来说的话,就是已经很久都没有那种写完满满一张纸的感觉,没有看完整整一本书的感觉,没有跑完操场一圈,没有听完一整首歌,也没有睡满整整一夜。总感觉还是缺一点什么。但我有很走心的去想了,可能是因为缺了每一个可爱的你。“如果是去见你,我会跑着去”刚看到这句话的时候,我也很赞同,因为毕竟去见一个想见了很久的人的时候,怎么也按捺不住你你内心的欣喜。到后来,当你真正去见ta的时候,你没有跑,你依然故作镇定的样子,只是你会比平时都迈的步子大一点,你担心你跑起来的样子不那么美观,你担心就算是夏天的微风也还是会把你轻薄的刘海吹乱。你会在意每个细节,你每次都希望你在ta面前是最好的状态。嗨,如果要去见你的话,我不跑着去了,我只想以我最好的状态去见你你像是我被子里的舒服你像是我右手背上的那颗痣你像是我眼角微微泛出来的光你像是我全身每一寸肌肤在呼吸你像是我枕头里的枕芯棉你像是我买过最好看书里的一页你像是我踩着云就可以飞上天你像是我走过的所有路途最想停留的瞬间你是我在夜晚闭上眼最后想到的人你是我在清晨睁开眼最先念起的人你是我的一日三餐你是我的一年四季来不及了不想再浪费时间昨天,今天,明天我还是最喜欢你总有一个人的出现,让我像流沙,像落雪。那些别人在上面划了又划的痕迹,你轻轻一抹,就平了。攒了一被子的情话,以后慢慢数给你听。希望认识更多可爱的人,一起做喜欢的事,写最纯真的字,讲有趣的故事。我是礼雪晶,那么你呢?作者:礼雪晶。“真羡慕你们这么年轻就遇到了这么才华横溢的我。”一个整天与数字对抗却藏了一被子情话的95后女生。愿你的深情不被辜负,你喜欢的人也喜欢你。

jieba 分词

segs = jieba.lcut(content[-1])
print(segs)
for seg in segs:
    if len(seg) > 1:
        print(seg)
['我', '攒', '了', '一', '被子', '的', '情话', ',', '想要', '说', '给', '你', '听', '最近', '有种', '很', '杂碎', '的', '感觉', ',', '嗯', '...', '如果', '用', '比喻', '修辞', '来说', '的话', ',', '就是', '已经', '很久', '都', '没有', '那种', '写', '完', '满满', '一张', '纸', '的', '感觉', ',', '没有', '看', '完', '整整', '一', '本书', '的', '感觉', ',', '没有', '跑', '完', '操场', '一圈', ',', '没有', '听', '完一', '整首歌', ',', '也', '没有', '睡满', '整整', '一夜', '。', '总', '感觉', '还是', '缺', '一点', '什么', '。', '但', '我', '有', '很', '走心', '的', '去', '想', '了', ',', '可能', '是因为', '缺', '了', '每', '一个', '可爱', '的', '你', '。', '“', '如果', '是', '去', '见', '你', ',', '我会', '跑', '着', '去', '”', '刚', '看到', '这句', '话', '的', '时候', ',', '我', '也', '很', '赞同', ',', '因为', '毕竟', '去', '见', '一个', '想见', '了', '很', '久', '的', '人', '的', '时候', ',', '怎么', '也', '按捺不住', '你', '你', '内心', '的', '欣喜', '。', '到', '后来', ',', '当', '你', '真正', '去', '见', 'ta', '的', '时候', ',', '你', '没有', '跑', ',', '你', '依然', '故作', '镇定', '的', '样子', ',', '只是', '你', '会', '比', '平时', '都', '迈', '的', '步子', '大', '一点', ',', '你', '担心', '你', '跑', '起来', '的', '样子', '不', '那么', '美观', ',', '你', '担心', '就算', '是', '夏天', '的', '微风', '也', '还是', '会', '把', '你', '轻薄', '的', '刘海', '吹乱', '。', '你', '会', '在意', '每个', '细节', ',', '你', '每次', '都', '希望', '你', '在', 'ta', '面前', '是', '最好', '的', '状态', '。', '嗨', ',', '如果', '要', '去', '见', '你', '的话', ',', '我', '不', '跑', '着', '去', '了', ',', '我', '只', '想', '以', '我', '最好', '的', '状态', '去', '见', '你', '你', '像是', '我', '被子', '里', '的', '舒服', '你', '像是', '我', '右手', '背上', '的', '那颗', '痣', '你', '像是', '我', '眼角', '微微', '泛出来', '的', '光', '你', '像是', '我', '全身', '每一寸', '肌肤', '在', '呼吸', '你', '像是', '我', '枕头', '里', '的', '枕芯', '棉', '你', '像是', '我', '买', '过', '最好', '看书', '里', '的', '一页', '你', '像是', '我', '踩', '着', '云', '就', '可以', '飞', '上天', '你', '像是', '我', '走过', '的', '所有', '路途', '最想', '停留', '的', '瞬间', '你', '是', '我', '在', '夜晚', '闭上眼', '最后', '想到', '的', '人', '你', '是', '我', '在', '清晨', '睁开眼', '最先', '念起', '的', '人', '你', '是', '我', '的', '一日三餐', '你', '是', '我', '的', '一年四季', '来不及', '了', '不想', '再', '浪费时间', '昨天', ',', '今天', ',', '明天', '我', '还是', '最', '喜欢', '你', '总有', '一个', '人', '的', '出现', ',', '让', '我', '像', '流沙', ',', '像', '落雪', '。', '那些', '别人', '在', '上面', '划', '了', '又', '划', '的', '痕迹', ',', '你', '轻轻', '一抹', ',', '就平', '了', '。', '攒', '了', '一', '被子', '的', '情话', ',', '以后', '慢慢', '数给', '你', '听', '。', '希望', '认识', '更', '多', '可爱', '的', '人', ',', '一起', '做', '喜欢', '的', '事', ',', '写', '最', '纯真', '的', '字', ',', '讲', '有趣', '的', '故事', '。', '我', '是', '礼雪晶', ',', '那么', '你', '呢', '?', '作者', ':', '礼雪晶', '。', '“', '真', '羡慕', '你们', '这么', '年轻', '就', '遇到', '了', '这么', '才华横溢', '的', '我', '。', '”', '一个', '整天', '与', '数字', '对抗', '却', '藏', '了', '一', '被子', '情话', '的', '95', '后', '女生', '。', '愿', '你', '的', '深情', '不', '被', '辜负', ',', '你', '喜欢', '的', '人', '也', '喜欢', '你', '。']
    被子
    情话
    想要
    最近
    有种
    杂碎
    感觉
    ...
    如果
    比喻
    修辞
    来说
    的话
    就是
    已经
    很久
    没有
segment = []
for line in content:
    try:
        segs = jieba.lcut(line)
        for seg in segs:
            if len(seg)>1 and seg != '\r\n':
                segment.append(seg)
    except:
        print(line)
        continue

载入停用词

words_df = pd.DataFrame({"segment": segment})
stopwords_df = pd.read_csv('Stopwords/Chinese_Stopwords.txt',index_col=False, quoting=3,sep="\t",names=['stopwords'], encoding='utf-8') #quoting=3全不引用
stopwords_df.head()

去掉停用词

words_df = words_df[~words_df.segment.isin(stopwords_df.stopwords)]
words_df.head()

统计词频

words_stat = words_df.groupby(by=['segment'])['segment'].agg({"计数": np.size})
words_stat = words_stat.reset_index().sort_values(by=["计数"], ascending=False)
words_stat.head(30)
words_stat.to_csv("JianShuJiaoYou-Words_Segments.csv", encoding='utf-8')

文章内容词云

丑版

wordcloud = WordCloud(font_path='simhei.ttf', background_color='white',max_font_size=80)
word_frequence = {x[0]:x[1] for x in words_stat.head(1000).values}
wordcloud = wordcloud.fit_words(word_frequence)
plt.imshow(wordcloud);
# plt.imsave(path)

自定义背景图 1.0版

简书交友专题 Logo


from scipy.misc import imread
matplotlib.rcParams['figure.figsize'] = (8.0, 8.0)
from wordcloud import WordCloud,ImageColorGenerator
bimg=imread('Logo-1.jpg')
wordcloud=WordCloud(background_color="white",mask=bimg,font_path='simhei.ttf',max_font_size=200)
word_frequence = {x[0]:x[1] for x in words_stat.head(1000).values}
wordcloud=wordcloud.fit_words(word_frequence)
bimgColors=ImageColorGenerator(bimg)
plt.axis("off")
plt.imshow(wordcloud.recolor(color_func=bimgColors));

自定义背景图 2.0版

中古民谣乐团Bloody Woods


from scipy.misc import imread
matplotlib.rcParams['figure.figsize'] = (8.0, 8.0)
from wordcloud import WordCloud,ImageColorGenerator
bimg=imread('中古民谣乐团Bloody Woods.jpg')
wordcloud=WordCloud(background_color="white",mask=bimg,font_path='simhei.ttf',max_font_size=200)
word_frequence = {x[0]:x[1] for x in words_stat.head(1000).values}
wordcloud=wordcloud.fit_words(word_frequence)
bimgColors=ImageColorGenerator(bimg)
plt.axis("off")
plt.imshow(wordcloud.recolor(color_func=bimgColors));

还是太丑

在线词云生成网站:HTML5 Word Cloud

图表太丑怎么破,ECharts神器带你飞
本次词云实例

标题词频、词云

title = df12.Title.values.tolist()
print(len(title), '\n', title[-1])
segment = []
for line in title:
    try:
        segs = jieba.lcut(line)
        for seg in segs:
            if len(seg)>1 and seg != '\r\n':
                segment.append(seg)
    except:
        print(line)
        continue
2718 
攒了一被子的情话,想说给你听
titles_df = pd.DataFrame({"segment": segment})
titles_df = titles_df[~titles_df.segment.isin(stopwords_df.stopwords)]
titles_df.head()
titles_stat = titles_df.groupby(by=['segment'])['segment'].agg({"计数": np.size})
titles_stat = titles_stat.reset_index().sort_values(by=["计数"], ascending=False)
titles_stat.head(30)
wordcloud = WordCloud(font_path='simhei.ttf', background_color='white',max_font_size=80)
word_frequence = {x[0]:x[1] for x in titles_stat.head(1000).values}
wordcloud = wordcloud.fit_words(word_frequence)
plt.imshow(wordcloud);

自定义背景图:Bloody Woods

from scipy.misc import imread
matplotlib.rcParams['figure.figsize'] = (8.0, 8.0)
from wordcloud import WordCloud,ImageColorGenerator
bimg=imread('中古民谣乐团Bloody Woods.jpg')
wordcloud=WordCloud(background_color="white",mask=bimg,font_path='simhei.ttf',max_font_size=200)
word_frequence = {x[0]:x[1] for x in titles_stat.head(1000).values}
wordcloud=wordcloud.fit_words(word_frequence)
bimgColors=ImageColorGenerator(bimg)
plt.axis("off")
plt.imshow(wordcloud.recolor(color_func=bimgColors));

在线词云生成网站:HTML5 Word Cloud

本次实例

简书“今日看点”专题热门文章标题词云

另一专题“今日看点”:简书=鸡汤?爬取简书今日看点:1916篇热门文章可视化

代码:GitHub - DesertsX / JianShuJiaoYou,后续更新LDA主题模型、word2vec词向量、文章照片爬取、人脸识别及颜值打分和照片墙等,敬请期待,欢迎star与指正。

PS:预告下,即将开启“Kaggle Kernel 学习系列”,GitHub - DesertsX / Kaggle-Kernel-Learning,欢迎star。

上一篇下一篇

猜你喜欢

热点阅读