excel还能这么操作?看掘力星爬虫就够了,你可能即将中奖噢!!!

3,546 阅读8分钟

本文已参与 「掘力星计划」 ,赢取创作大礼包,挑战创作激励金。

前言

掘力星计划正如火如荼进行中,只剩一周就要结束了,你是否好奇有多人参加?写了多少篇文章?各个端的文章分布?...和胖头鱼一起一探究竟吧O(∩_∩)O哈哈~

郑重声明

1. 文章仅从某些侧面了解相关数据,具体结果以官方为主,别信本文o(╥﹏╥)o

2. 文章只做学习参考使用,无任何恶意

3. 文章数据来源 掘力星计划 - 参与活动文章 截止10.22号的数据

4. 篇幅原因部分维度(如投稿数、阅读量等只截取了前30位数据)

5. 祝愿我们在掘金写作路上越来越好,写出更多好文章

源码实现

整体思路

以下是从10.01号到10.22号的大致数据,我们来看看是如何获取到的吧!!!

1.数据源

要拿到以下数据我们首先需要数据源,当然数据源就是掘金运营大大维护的这张excel表,原本以为可以直接把表格下载下来,但是没有找到入口,所以只能手动复制粘贴到本地excel中了。

2. 读取excel数据

读取第一步数据源中的数据,可以借助开源库xlsx,非常方便转化为前端需要的json数据,比如我们有下面的一张excel表格

image.png

image.png

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我们也可以很方便地完成此操作,例如要实现如下表格。

image.png

image.png


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
android30
ios12

各端写文章人数分布

羡慕能写10几篇甚至几十篇的同学,为什么可以做到如此高产?

不同端1篇2篇3 ~ 4篇6 ~ 10篇11 ~ 20篇21+篇
前端51303831124
后端282033312110
android6451221
ios313320

投稿数

用户名投稿数
Mancuoj67
陈言必行28
西瓜watermelon27
是洋柿子啊23
陈_杨19
前端老实人19
仙儿仙儿15
_Battle14
YK菌14
jsmask14
stevezhao614
速冻鱼12
请叫我阿ken11
海的对岸11
Axjy11
BraveWang11
a尘ss10
时光足迹9
tangxd39
zekelove9
xn2138
早起的年轻人_坚果8
战场小包7
明天也要努力7
小科比_7
鱼酱7
静Yu7
呆呆敲代码的小Y6
尽管如此世界依然美丽6
安逸的咸鱼6

阅读量

用户名阅读量
前端胖头鱼76286
红尘炼心65526
阿Tya43850
Sunshine_Lin31597
陈_杨18936
_Battle15347
前端picker14022
前端小智13956
掘金安东尼13908
YK菌13048
CUGGZ12884
jsmask10560
獨釣寒江雪10227
谭光志10062
快跑啊小卢_8977
寒草8220
why技术7625
呆呆敲代码的小Y7152
Ned6417
Mancuoj6325
明天也要努力6200
尽管如此世界依然美丽6081
云的世界5892
冰冰你个小可爱5570
前端老实人5567
大帅老猿5086
DevUI团队4245
时光足迹4198
浅煅熕澄湿4196
战场小包4167

点赞数

用户名点赞数
红尘炼心2613
前端胖头鱼2595
Sunshine_Lin1451
阿Tya966
Mancuoj901
_Battle626
CUGGZ539
前端picker432
谭光志415
快跑啊小卢_399
前端小智398
请叫我阿ken380
陈_杨359
掘金安东尼348
陈言必行324
战场小包281
YK菌273
前端老实人266
獨釣寒江雪213
呆呆敲代码的小Y209
海拥194
jsmask192
尽管如此世界依然美丽167
浅煅熕澄湿161
寒草156
云的世界150
冰冰你个小可爱148
速冻鱼133
why技术126
明天也要努力123

评论数

用户名评论数
红尘炼心527
前端胖头鱼383
阿Tya223
Sunshine_Lin160
前端picker111
Mancuoj72
尽管如此世界依然美丽70
冰冰你个小可爱68
陈_杨67
CUGGZ64
Curly_Brackets61
寒草60
快跑啊小卢_59
YK菌57
獨釣寒江雪53
_Battle50
呆呆敲代码的小Y50
前端小智49
速冻鱼46
战场小包45
vaelcy43
jsmask42
云的世界41
陈言必行40
海拥38
why技术36
ndz36
DevUI团队35
Ned34
AEI34

收藏数

用户名收藏数
前端胖头鱼3849
红尘炼心2930
Sunshine_Lin2226
CUGGZ1047
阿Tya988
快跑啊小卢_549
前端小智526
陈_杨522
谭光志499
掘金安东尼442
前端picker367
_Battle268
獨釣寒江雪239
橙某人175
战场小包156
明天也要努力148
iwhao140
浅煅熕澄湿134
大帅老猿114
jsmask112
冰冰你个小可爱109
海拥106
云的世界95
前端老实人90
时光足迹90
HelloGitHub85
Mancuoj84
Ned81
政采云前端团队77
dragonir76

结尾

「欢迎在评论区讨论,掘金官方将在掘力星计划活动结束后,在评论区抽送100份掘金周边,抽奖详情见活动文章」