本文已参与 「掘力星计划」 ,赢取创作大礼包,挑战创作激励金。
前言
掘力星计划正如火如荼进行中,只剩一周就要结束了,你是否好奇
有多人参加?
、写了多少篇文章?
、各个端的文章分布?
...和胖头鱼一起一探究竟吧O(∩_∩)O哈哈~
郑重声明
1. 文章仅从某些侧面了解相关数据,具体结果以官方为主,别信本文o(╥﹏╥)o
2. 文章只做学习参考使用,无任何恶意
3. 文章数据来源 掘力星计划 - 参与活动文章 截止10.22号的数据
4. 篇幅原因
部分维度(如投稿数、阅读量等只截取了前30位数据)
5. 祝愿我们在掘金写作路上越来越好,写出更多好文章
源码实现
整体思路
以下是从10.01号到10.22号的大致数据,我们来看看是如何获取到的吧!!!
1.数据源
要拿到以下数据我们首先需要数据源,当然数据源就是掘金运营大大维护的这张excel表,原本以为可以直接把表格下载下来,但是没有找到入口,所以只能手动复制粘贴到本地excel中了。
2. 读取excel数据
读取第一步数据源中的数据,可以借助开源库xlsx,非常方便转化为前端需要的json数据,比如我们有下面的一张excel表格
const XLSX = require('xlsx')
// 读取文件数据
const workbook = XLSX.readFile('./read.xlsx')
const articalClassifyInfo = workbook.Sheets
for (sheetName in articalClassifyInfo) {
// 工作区数据
console.log(sheetName, XLSX.utils.sheet_to_json(workbook.Sheets[sheetName]))
}
/*
表格1 [ { name: '前端胖头鱼', age: 100 } ]
表格2 [ { name: '前端胖头鱼2', age: 1000 } ]
*/
3. 写入excel数据
整个方案不仅需要读取数据,还需要将最后的结果写入到excel中,当然啦,借助
xlsx
我们也可以很方便地完成此操作,例如要实现如下表格。
const XLSX = require('xlsx')
// 数据json
const ws1Json = [
{
'姓名': '前端胖头鱼1',
'年龄': 100
},
{
'姓名': '前端胖头鱼1',
'年龄': 1000
},
]
const ws2Json = [
{
'姓名': '前端胖头鱼2',
'年龄': 200
},
{
'姓名': '前端胖头鱼2',
'年龄': 2000
},
]
// 表示一个excel
const wb = XLSX.utils.book_new()
// excel中的一个sheet
const ws1 = XLSX.utils.json_to_sheet(ws1Json)
// excel中的一个sheet
const ws2 = XLSX.utils.json_to_sheet(ws2Json)
// 将数据sheet添加到excel
XLSX.utils.book_append_sheet(wb, ws1, '表格1')
// 将数据sheet添加到excel
XLSX.utils.book_append_sheet(wb, ws2, '表格2')
// 写文件
XLSX.writeFile(wb, './write.xlsx')
是不是感觉很简单,不需要过多的理解excel本身的东西,就可以完成excel的读写操作
4. 获取文章详情接口
一篇文章的详情,例如
阅读量
、评论数
、点赞数
、收藏数
可以通过该接口获取,入参只需要文章ID即可
// 请求参数
method: 'post'
url: 'https://api.juejin.cn/content_api/v1/article/detail'
data: {
article_id: 'xxx'
}
// 响应值,这里只列出我们关注的数据
const { article_info, author_user_info } = result.data.data || {}
// 浏览量 点赞数 评论数 收藏数
const { view_count: viewCount, digg_count: diggCount, comment_count: commentCount, collect_count: collectCount } = article_info || {}
// 用户名 userId
const { user_name: userName, user_id: userId } = author_user_info || {}
4. 整体实现
const axios = require('axios')
const randomUa = require('random-ua')
const XLSX = require('xlsx')
// 获取文章分类简讯
const getClassifyInfo = () => {
const workbook = XLSX.readFile('./star.xlsx')
return workbook.Sheets
}
// 获取单篇文章详情
const getArticalDetail = async (articleId) => {
return new Promise(async (resolve) => {
let resultData = null
try {
const result = await axios({
method: 'post',
url: 'https://api.juejin.cn/content_api/v1/article/detail',
data: {
article_id: articleId
},
headers: {
origin: 'https://juejin.cn',
referer: 'https://juejin.cn/',
'user-agent': randomUa.generate()
}
})
const { article_info, author_user_info } = result.data.data || {}
// 浏览量 点赞数 评论数 收藏数
const { view_count: viewCount, digg_count: diggCount, comment_count: commentCount, collect_count: collectCount } = article_info || {}
// 用户名 userId
const { user_name: userName, user_id: userId } = author_user_info || {}
resultData = {
userName,
userId,
viewCount,
diggCount,
commentCount,
collectCount
}
} catch (err) {
console.log('获取单篇文章出错,文章ID是:', articleId)
}
resolve(resultData)
})
}
// 随机随眠一段时间,防止被命中爬虫风控
const sleep = (timeout) => {
return new Promise((resolve) => {
setTimeout(() => {
resolve()
}, timeout)
})
}
const init = async () => {
const articalClassifyInfo = getClassifyInfo()
const wb = XLSX.utils.book_new()
let count = 0
let startTime = Date.now()
// articalClassifyInfo中有前端、后端、android、ios四个sheet
for (sheetName in articalClassifyInfo) {
// 读取每个sheet的内容,是个数组
const sheetContent = XLSX.utils.sheet_to_json(articalClassifyInfo[sheetName])
let sheetJson = {}
for (classifyInfo of sheetContent) {
// 读取链接,截取文章id
const articalLink = classifyInfo['链接']
const articalId = articalLink.match(/\/(\d+)/)[1]
count += 1
// 随机随眠一会
await sleep(Math.random())
console.log(`-------开始获取${articalLink}文章数据, 第${count}篇文章`)
const articalDetail = await getArticalDetail(articalId)
console.log(`-------获取${articalLink}文章数据结束`)
const name1 = '用户名'
const name2 = '投稿数'
const name3 = '阅读量'
const name4 = '点赞数'
const name5 = '评论数'
const name6 = '收藏数'
const originArticaldetail = sheetJson[articalDetail.userId] || {}
// 根据userId作为唯一的key,统计每位作者的文章数据
sheetJson[articalDetail.userId] = {
[ name1 ]: articalDetail.userName,
[ name2 ]: (originArticaldetail[ name2 ] || 0) + 1,
[ name3 ]: (originArticaldetail[ name3 ] || 0) + articalDetail.viewCount,
[ name4 ]: (originArticaldetail[ name4 ] || 0) + articalDetail.diggCount,
[ name5 ]: (originArticaldetail[ name5 ] || 0) + articalDetail.commentCount,
[ name6 ]: (originArticaldetail[ name6 ] || 0) + articalDetail.collectCount,
}
}
// 生成每张sheet数据表
const ws = XLSX.utils.json_to_sheet(Object.values(sheetJson))
XLSX.utils.book_append_sheet(wb, ws, sheetName)
}
let endTime = Date.now()
console.log('整体耗时', endTime - startTime)
// 写入excel
XLSX.writeFile(wb, 'out.xlsx')
}
init()
数据概览
各端写作人数
前端还是太卷了 o(╥﹏╥)o
不同端 | 人数 |
---|---|
前端 | 165 |
后端 | 143 |
android | 30 |
ios | 12 |
各端写文章人数分布
羡慕能写10几篇甚至几十篇的同学,为什么可以做到如此高产?
不同端 | 1篇 | 2篇 | 3 ~ 4篇 | 6 ~ 10篇 | 11 ~ 20篇 | 21+篇 |
---|---|---|---|---|---|---|
前端 | 51 | 30 | 38 | 31 | 12 | 4 |
后端 | 28 | 20 | 33 | 31 | 21 | 10 |
android | 6 | 4 | 5 | 12 | 2 | 1 |
ios | 3 | 1 | 3 | 3 | 2 | 0 |
投稿数
用户名 | 投稿数 |
---|---|
Mancuoj | 67 |
陈言必行 | 28 |
西瓜watermelon | 27 |
是洋柿子啊 | 23 |
陈_杨 | 19 |
前端老实人 | 19 |
仙儿仙儿 | 15 |
_Battle | 14 |
YK菌 | 14 |
jsmask | 14 |
stevezhao6 | 14 |
速冻鱼 | 12 |
请叫我阿ken | 11 |
海的对岸 | 11 |
Axjy | 11 |
BraveWang | 11 |
a尘ss | 10 |
时光足迹 | 9 |
tangxd3 | 9 |
zekelove | 9 |
xn213 | 8 |
早起的年轻人_坚果 | 8 |
战场小包 | 7 |
明天也要努力 | 7 |
小科比_ | 7 |
鱼酱 | 7 |
静Yu | 7 |
呆呆敲代码的小Y | 6 |
尽管如此世界依然美丽 | 6 |
安逸的咸鱼 | 6 |
阅读量
用户名 | 阅读量 |
---|---|
前端胖头鱼 | 76286 |
红尘炼心 | 65526 |
阿Tya | 43850 |
Sunshine_Lin | 31597 |
陈_杨 | 18936 |
_Battle | 15347 |
前端picker | 14022 |
前端小智 | 13956 |
掘金安东尼 | 13908 |
YK菌 | 13048 |
CUGGZ | 12884 |
jsmask | 10560 |
獨釣寒江雪 | 10227 |
谭光志 | 10062 |
快跑啊小卢_ | 8977 |
寒草 | 8220 |
why技术 | 7625 |
呆呆敲代码的小Y | 7152 |
Ned | 6417 |
Mancuoj | 6325 |
明天也要努力 | 6200 |
尽管如此世界依然美丽 | 6081 |
云的世界 | 5892 |
冰冰你个小可爱 | 5570 |
前端老实人 | 5567 |
大帅老猿 | 5086 |
DevUI团队 | 4245 |
时光足迹 | 4198 |
浅煅熕澄湿 | 4196 |
战场小包 | 4167 |
点赞数
用户名 | 点赞数 |
---|---|
红尘炼心 | 2613 |
前端胖头鱼 | 2595 |
Sunshine_Lin | 1451 |
阿Tya | 966 |
Mancuoj | 901 |
_Battle | 626 |
CUGGZ | 539 |
前端picker | 432 |
谭光志 | 415 |
快跑啊小卢_ | 399 |
前端小智 | 398 |
请叫我阿ken | 380 |
陈_杨 | 359 |
掘金安东尼 | 348 |
陈言必行 | 324 |
战场小包 | 281 |
YK菌 | 273 |
前端老实人 | 266 |
獨釣寒江雪 | 213 |
呆呆敲代码的小Y | 209 |
海拥 | 194 |
jsmask | 192 |
尽管如此世界依然美丽 | 167 |
浅煅熕澄湿 | 161 |
寒草 | 156 |
云的世界 | 150 |
冰冰你个小可爱 | 148 |
速冻鱼 | 133 |
why技术 | 126 |
明天也要努力 | 123 |
评论数
用户名 | 评论数 |
---|---|
红尘炼心 | 527 |
前端胖头鱼 | 383 |
阿Tya | 223 |
Sunshine_Lin | 160 |
前端picker | 111 |
Mancuoj | 72 |
尽管如此世界依然美丽 | 70 |
冰冰你个小可爱 | 68 |
陈_杨 | 67 |
CUGGZ | 64 |
Curly_Brackets | 61 |
寒草 | 60 |
快跑啊小卢_ | 59 |
YK菌 | 57 |
獨釣寒江雪 | 53 |
_Battle | 50 |
呆呆敲代码的小Y | 50 |
前端小智 | 49 |
速冻鱼 | 46 |
战场小包 | 45 |
vaelcy | 43 |
jsmask | 42 |
云的世界 | 41 |
陈言必行 | 40 |
海拥 | 38 |
why技术 | 36 |
ndz | 36 |
DevUI团队 | 35 |
Ned | 34 |
AEI | 34 |
收藏数
用户名 | 收藏数 |
---|---|
前端胖头鱼 | 3849 |
红尘炼心 | 2930 |
Sunshine_Lin | 2226 |
CUGGZ | 1047 |
阿Tya | 988 |
快跑啊小卢_ | 549 |
前端小智 | 526 |
陈_杨 | 522 |
谭光志 | 499 |
掘金安东尼 | 442 |
前端picker | 367 |
_Battle | 268 |
獨釣寒江雪 | 239 |
橙某人 | 175 |
战场小包 | 156 |
明天也要努力 | 148 |
iwhao | 140 |
浅煅熕澄湿 | 134 |
大帅老猿 | 114 |
jsmask | 112 |
冰冰你个小可爱 | 109 |
海拥 | 106 |
云的世界 | 95 |
前端老实人 | 90 |
时光足迹 | 90 |
HelloGitHub | 85 |
Mancuoj | 84 |
Ned | 81 |
政采云前端团队 | 77 |
dragonir | 76 |
结尾
「欢迎在评论区讨论,掘金官方将在掘力星计划活动结束后,在评论区抽送100份掘金周边,抽奖详情见活动文章」