CSDN2018博客之星評選結果預測第二彈
CSDN2018博客之星活動開始之初,出於個人娛樂,我做了一次《大數據預測CSDN2018博客之星評選結果》,受到了較多好評,當然也十分榮幸的受到CSDN官方重視,並將文章放置在Banner推廣位。
至今,CSDN2018博客之星的評選結果即將出爐。我很榮幸收到了CSDN官方的邀請,他們希望我能夠在結果出爐之前再次作出一次大膽預測。所以,我將再次開啓大膽預測。
閒話不多說,我們開始:
首先,如果你關注過這個活動,那麼你應該知道,CSDN2018博客之星評選活動參選人員入選博主名單可以在以下網址看到 https://bss.csdn.net/m/topic/blog_star2018
即:
時間尚未截止,有心怡的博主入選還沒有投票的,趕緊去投上一票吧。
那麼,截止到本文出爐爲止,200位入選博主的原創/粉絲/喜歡/評論/等級/訪問/積分/排名/獲得選票 各指標信息如何呢?
指標 | 最大值 | 最小值 | 平均值 | 總計 | 最佳用戶列表 |
---|---|---|---|---|---|
原創 | 2327 |
29 | 292 | 58582 | [‘迂者-賀利堅’] |
粉絲 | 22564 |
47 | 2093 | 418649 | [‘迂者-賀利堅’] |
喜歡 | 6466 |
8 | 694 | 138967 | [‘foruok’] |
評論 | 7360 |
3 | 622 | 124528 | [‘迂者-賀利堅’] |
等級 | 10 |
3 | 6 | 1285 | [‘dog250’, ‘迂者-賀利堅’] |
訪問 | 11084501 |
50663 | 1590813 | 318162704 | [‘china_jeffery’] |
積分 | 107000 |
507 | 14762 | 2952414 | [‘迂者-賀利堅’] |
排名 | 125326 | 12 |
6532 | 1306538 | [‘迂者-賀利堅’] |
投票 | 2823 |
20 | 141 | 28335 | [‘徐劉根’] |
由上面的表格我們可以得出的結論。
- 目前獲得票數最高的是
徐劉根
博主,並且獲得選票高達2823
票,人氣相當火爆。 - 目前文章最高總訪問次數由
china_jeffery
博主拿下,並且訪問次數高達11084501
。 - 目前文章總點贊次數由
foruok
博主拿下,並且已經獲得了6466
點贊。 - 截止目前爲止,其他各項指標,包括最佳排名(
12
),最佳收藏(2327
),最多原創(13687181
),最高積分(107000
),最高等級(10
),最多粉絲(22564
),最多評論(7360
)均由迂者-賀利堅
博主砍下,這個成績可是相當恐怖的。
這裏我們再重點關注一下,截止目前爲止對於200位入選博主的投票情況。
指標 | 最大值 | 最小值 | 平均值 | 總計 |
---|---|---|---|---|
投票 | 2823 |
20 |
141 |
28335 |
即:
- 目前總計只有
28335
位用戶參與了投票,還沒有參與過投票的博主記得給自己心怡的博主投上一票啊。(對於具有500萬註冊程序員用戶的CSDN來說,這個參與投票人數確實有點少啊) - 目前入選200位博主平均獲得選票有
141
票。(多項指標成績最佳的迂者-賀利堅
博主的選票目前還沒到平均線,各位粉絲們要給力啊)
然後,我們再關注一下,目前排名前十的得票博主
排名 | 得票 | 博主 |
---|---|---|
1 | 2823 | 徐劉根 |
2 | 1549 | LovelyBear2019 |
3 | 1336 | 肖朋偉 |
4 | 1136 | ECMAScripter |
5 | 1111 | 劉望舒 |
6 | 999 | 方誌朋 |
7 | 836 | Soyoger |
8 | 648 | analogous_love |
9 | 576 | Eastmount |
10 | 554 | 虛無境 |
第二名與第一名的差距還是相當的大啊。大家要火熱開啓投票節奏啊!
接下來,我們再看一下,入選的200位博主,目前博客等級排名
等級 | 人數 |
---|---|
10 | 2 |
9 | 3 |
8 | 18 |
7 | 83 |
6 | 50 |
5 | 39 |
4 | 3 |
3 | 2 |
由此看來,報名入選博主在CSDN的等級分佈還是比較均勻的,縱使你目前的博客等級不是很高,只有文章質量可以也還是有機會的。
接下來,我們再看一下,入選的200位博主目前已經獲得的榮譽勳章情況如下
勳章 | 人數 |
---|---|
持之以恆 | 170 |
微軟mvp | 1 |
博客之星 | 6 |
博客專家 | 191 |
專欄達人 | 177 |
1024超級勳章 | 3 |
1024活動勳章 | 43 |
即:
6
位作者已經拿過博客之星勳章,並且發起了再次衝擊。3
位作者拿到了1024超級勳章勳章,這意味着有超過3位報名作者的原創文章超過了1024篇,堪稱超級寫手。191
位已經拿到博客專家,當然也有9位目前尚未拿到博客專家稱號,說明沒有博客專家稱號也還是有機會的。
當然,我們在投票之餘,也可以多多關注一下大佬博主們的文章,看看這些博主專家們的研究方向,看看技術熱點,作爲我們2019年的學習方向。我這裏還是老規矩爲大家貢獻一張目前已入選博主的所有專欄相關課題研究方向熱力圖供大家參考。
技術實現分析
知其然亦知其所以然,如果大家也有興趣做類似的技術分析或者想要進一步深入技術發掘分析,我們再一起看看我們是怎麼分析的。
數據挖掘
首先,我們知道 入選博主名單可以在 https://bss.csdn.net/m/topic/blog_star2018 網址看到,那麼自然我們分析信息需要從這裏出發。
想必你也猜到了,我們需要首先爬取所有的入選博主。如果對於爬蟲不太瞭解可以從我的Scrapy專欄或者前一篇文章《大數據預測CSDN2018博客之星評選結果》瞭解詳細,我這裏就不深入了。例如,我們可以從這裏拿到入選博主的基礎信息
# -*- coding: utf-8 -*-
import scrapy
import json
from tutorial.items import BlogStar2018Item
class BlogStar2018Spider(scrapy.Spider):
name = 'blog_star2018'
allowed_domains = ['blog.csdn.net']
start_urls = ['https://bss.csdn.net/m/topic/blog_star2018']
def parse(self, response):
for user_info in response.xpath('//div[@class="user-info"]'):
info = {}
user_id = user_info.xpath('./div[@class="user-id"]/text()').extract_first()
user_addr = user_info.xpath('./div[@class="avatar"]/a/@href').extract_first()
user_name = user_info.xpath('./div[@class="user-name"]/span/text()').extract_first()
user_number = user_info.xpath('./div[@class="user-number"]/span/em/text()').extract_first()
print(user_id,user_addr,user_name,user_number)
info['user_id'] = user_id
info['user_addr'] = user_addr
info['user_name'] = user_name
info['user_number'] = user_number
yield scrapy.Request(user_addr,
callback=lambda response, info=info: self.parse_blog_user_info(response,info))
當然,只知道那些博主入選了本次評選是遠遠不夠的,我們還需要知道包括但不限於 原創/粉絲/喜歡/評論/等級/訪問/積分/排名/專欄/技術方向 等等信息。例如,我們可以利用分析工具抓取所有的入選博主的專欄信息
def parse_blog_user_info(self,response,info):
item = BlogStar2018Item()
item['link'] = response.request.url
item['blogstar_vote'] = info
item['blog_title'] = response.xpath('//div[@class="title-box"]/h1[@class="title-blog"]/a/text()').extract_first()
item['description'] = response.xpath('//p[@class="description"]/text()').extract_first()
item['avatar_pic'] = response.xpath('//div[@class="profile-intro d-flex"]/div[@class="avatar-box d-flex justify-content-center flex-column"]/a/img/@src').extract_first()
for data in response.xpath('//div[@class="data-info d-flex item-tiling"]/dl[@class="text-center"]'):
data_key = data.xpath('./dt/a/text() | ./dt/text()').extract_first()
data_value = data.xpath('./@title').extract_first()
if data_key.find('原創') > -1:
item['original'] = int(data_value)
elif data_key.find('粉絲') > -1:
item['fans'] = int(data_value)
elif data_key.find('喜歡') > -1:
item['star'] = int(data_value)
elif data_key.find('評論') > -1:
item['comment'] = int(data_value)
for grade in response.xpath('//div[@class="grade-box clearfix"]/dl'):
grade_key = grade.xpath('./dt/text()').extract_first()
grade_value = grade.xpath('./dd/@title | ./dd/a/@title | ./@title').extract_first()
if grade_key.find('等級') > -1:
item['level'] = int(grade_value.replace('級,點擊查看等級說明',''))
elif grade_key.find('訪問') > -1:
item['visit'] = int(grade_value)
elif grade_key.find('積分') > -1:
item['score'] = int(grade_value)
elif grade_key.find('排名') > -1:
item['rank'] = int(grade_value)
#勳章
item['medal'] = response.xpath('//div[@class="badge-box d-flex"]/div[@class="icon-badge"]/@title').extract()
blog_expert = ''.join(response.xpath('//div[@class="user-info d-flex justify-content-center flex-column"]/p[@class="flag expert"]/text()').extract()).replace('\n','').replace(' ','')
if blog_expert and '' is not blog_expert :
item['medal'].append(blog_expert)
#博主專欄
colunms = []
for li in response.xpath('//div[@id="asideColumn"]/div[@class="aside-content"]/ul/li'):
colunms.append({'colunm_name':li.xpath('./div[@class="info"]/p/a/text()').extract_first()
,
'colunm_count': li.xpath('./div[@class="info"]/div[@class="data"]/span/text()').extract_first().replace(' ', '').replace('篇',
'')
,
'colunm_read': li.xpath('./div[@class="info"]/div[@class="data"]/span/text()').extract()[-1].replace(' ', '')})
item['colunms'] = colunms
yield item
當然,我們也可以繼續抓取更多信息,這裏就留給大家擴展了。
數據存儲與分析
我們都知道,空有了數據來源,不能對數據做出存儲與分析,等於什麼都沒做,所以,我們需要對我們的數據作出存儲與分析。
數據存儲
我們這裏還是使用Elasticsearch 做數據存儲,如果對Elasticsearch有興趣,希望學習的話,可以到我的專欄查看,我這裏就不展開了,我這裏給大家分享一下,我這邊建立的數據存儲索引。
PUT blogstar2018
{
"mappings":{
"blogstar2018":{
"properties":{
"link": {
"type": "keyword",
"index": false
},
"blog_title":{
"type": "text",
"analyzer": "ik_smart",
"fielddata": true
},
"description":{
"type": "text",
"analyzer": "ik_smart",
"fielddata": true
},
"avatar_pic": {
"type": "keyword",
"index": false
},
"original":{
"type": "long"
},
"fans":{
"type": "long"
},
"star":{
"type": "long"
},
"comment":{
"type": "long"
},
"level":{
"type": "long"
},
"visit":{
"type": "long"
},
"score":{
"type": "long"
},
"rank":{
"type": "long"
},
"medal":{
"type": "text",
"analyzer": "ik_smart",
"fielddata": true
},
"colunms":{
"type": "nested",
"properties": {
"colunm_name":{
"type": "text",
"analyzer": "ik_smart",
"fielddata": true
},
"colunm_count":{
"type": "long"
},
"colunm_read":{
"type": "long"
}
}
},
"blogstar_vote":{
"type": "object",
"properties": {
"user_id":{
"type": "keyword"
},
"user_addr":{
"type": "keyword"
},
"user_name":{
"type": "keyword"
},
"user_number":{
"type": "long"
}
}
}
}
}
}
}
數據字段不是很多,我這裏就不再做詳細分析了,這裏需要注意,我們的文本使用的大多都是中文,所以我們需要使用中文的分詞起IK_SMART。
數據分析
當我們成功抓取到數據並存儲以後呢,我們需要對我們的數據加以分析才能夠發揮出它的作用。
#! /usr/bin/env python3
# -*- coding:utf-8 -*-
import elasticsearch
class BlogStar2018(object):
index = 'blogstar2018'
es = elasticsearch.Elasticsearch(['sc.es.com:80'])
@classmethod
def index_doc(cls,body):
cls.es.index(index=cls.index, doc_type=cls.index, body=body)
@classmethod
def match_all(cls):
body = {
"query": {
"match_all": {}
},
"size": 1000
}
try:
res = cls.es.search(index=cls.index, doc_type=cls.index, body=body)
except Exception as e:
print('查詢失敗 ', str(e))
res = None
return res
@classmethod
def count_doc(cls):
try:
res = cls.es.count(index=cls.index, doc_type=cls.index,)
except Exception as e:
print('查詢失敗 ', str(e))
return 0
return res['count']
@classmethod
def stats_aggs(cls,field):
body = {
"size": 0,
"aggs": {
"stats_"+field: {
"stats": {
"field": field
}
}
}
}
try:
res = cls.es.search(index=cls.index, doc_type=cls.index, body=body)
except Exception as e:
print('查詢失敗 ', str(e))
res = None
return res
@classmethod
def term_aggs(cls,field,size=10):
body = {
"size": 0,
"aggs": {
"term_"+field: {
"terms": {
"field": field,
"size": size,
"order": {
"_key": "desc"
}
}
}
}
}
try:
res = cls.es.search(index=cls.index, doc_type=cls.index, body=body)
except Exception as e:
print('查詢失敗 ', str(e))
res = None
return res
@classmethod
def term_query(cls,field,value):
body = {
"query": {
"bool": {
"filter": {
"term": {
field: value
}
}
}
}
}
try:
res = cls.es.search(index=cls.index, doc_type=cls.index, body=body)
except Exception as e:
print('查詢失敗 ', str(e))
res = None
return res
@classmethod
def username_term_query(cls,field,value):
body = {
"query": {
"bool": {
"filter": {
"term": {
field: value
}
}
}
},
"_source": ["blogstar_vote.user_name"]
}
try:
res = cls.es.search(index=cls.index, doc_type=cls.index, body=body)
except Exception as e:
print('查詢失敗 ', str(e))
res = None
return res
@classmethod
def stat_colunm_name(cls):
body = {
"aggs": {
"colunms": {
"nested": {
"path": "colunms"
},
"aggs": {
"colunm_name": {
"terms": {
"field": "colunms.colunm_name",
"size": 1000
}
}
}
}
}
}
try:
res = cls.es.search(index=cls.index, doc_type=cls.index, body=body)
except Exception as e:
print('查詢失敗 ', str(e))
res = None
return res
blogstar2018_analyzer.py
#! /usr/bin/env python3
# -*- coding:utf-8 -*-
import sys
sys.path.append('../..')
import json
import re
from backend.models.es.BlogStar2018 import BlogStar2018
from pyecharts import Bar,WordCloud
if __name__ == '__main__':
# field_dict = {'original':'原創','fans':'粉絲','star':'喜歡','comment':'評論','level':'等級','visit':'訪問','score':'積分','rank':'排名','blogstar_vote.user_number':'投票'}
#
# print('報名總人數:',BlogStar2018.count_doc())
# field_stats_dict = {}
# for field in field_dict.keys():
# res = BlogStar2018.stats_aggs(field)
# if res:
# field_stats_dict[field] = {
# 'max': int(res['aggregations']['stats_'+field]['max']),
# 'min': int(res['aggregations']['stats_'+field]['min']),
# 'avg': int(res['aggregations']['stats_'+field]['avg']),
# 'sum': int(res['aggregations']['stats_'+field]['sum'])
# }
# print('指標','|','最大值','|','最小值','|','平均值','|','總計','|','最佳用戶列表')
# print('|:------:|:---------:|:---------:|:---------:|:---------:|:-----------:|')
# for field in field_dict.keys():
# print(field_dict[field],'|',field_stats_dict[field]['max'],'|',field_stats_dict[field]['min'],
# '|', field_stats_dict[field]['avg'],'|',field_stats_dict[field]['sum'],
# '|',[hit['_source']['blogstar_vote']['user_name'] for hit in BlogStar2018.username_term_query(field, field_stats_dict[field]['min' if 'rank' == field else 'max'])['hits']['hits']])
#
# level_aggs_res = BlogStar2018.term_aggs('level')
# print('等級','|','人數')
# print('------|-----')
# if level_aggs_res :
# for bucket in level_aggs_res['aggregations']['term_level']['buckets']:
# print(bucket['key'],'|',bucket['doc_count'])
#
# print('勳章','|','人數')
# print('------|-----')
# medal_aggs_res = BlogStar2018.term_aggs('medal')
# if medal_aggs_res:
# for bucket in medal_aggs_res['aggregations']['term_medal']['buckets']:
# print(bucket['key'],'|',bucket['doc_count'])
white_hotkey_list = ['分佈式','算法','嵌入式','前端','機器學習','公衆號','微信公衆號','數據庫','計算機','人工智能','後端','框架','數據結構','程序','大數據',
'程序設計','計算機網絡','網絡','視覺','數據','圖像','小程序','圖像分析','操作系統','架構','安卓','微服務','爬蟲','設計模式']
wordcloud = WordCloud(width=1300, height=900)
name = []
value = []
for i,bucket in enumerate(BlogStar2018.stat_colunm_name()['aggregations']['colunms']['colunm_name']['buckets']):
if re.compile(u'[\u4e00-\u9fa5]').search(bucket['key']) :
if bucket['key'] in white_hotkey_list:
name.append(bucket['key'])
value.append(bucket['doc_count'])
elif re.findall('[a-zA-Z]+', bucket['key']) :
if bucket['key'].find('http') == -1 and bucket['key'].find('csdn') == -1 and 'details'!=bucket['key'] and '1&orderby'!=bucket['key']:
name.append(bucket['key'])
value.append(bucket['doc_count'])
wordcloud.add("", name, value, word_size_range=[30, 120])
wordcloud.render('blogstar_csdn.html')
感謝您的閱讀,新年新氣象,祝您,新年快樂,闔家歡樂。