Giter VIP home page Giter VIP logo

juejin-spider's Introduction

juejin-spider

关注者、点赞数、评论数历史数据变化

在输入框输入用户主页的 url 搜索。例如我的主页是 https://juejin.im/user/57a0c28979bc440054958498

排名历史变化查看 排名历史变化查看

文章教你如何做掘金站内数据抓取,数据解析,最后形成排序后的排名。

数据来源于掘金,如有侵权,请联系 [email protected] 删除


项目起因是我突然想看看掘金站内有哪些优质作者,为了不错过每一个大佬,我选择直接抓取站内所有的文章信息找到作者并进行排名。各位关注 + 文章阅读 一条龙走起!

项目地址 juejin-spider 欢迎 star issue

掘金 spider 和数据分析,主要关注了下面几个排行和统计,排行点击直接查看

先上掘金前 50 排名,关注一波???? 前 5000 排名看这里

🎉 等级,👦 关注数,🏠 公司

脚本

全站标签抓取

获取掘金站内所有标签信息

npm run tagList

会把标签信息写入到 src/assets/tagList/tagList.json,每个标签包含下面的信息,主要是 titleid

{
  "id": "5597a063e4b08a686ce57030",
  "title": "后端",
  "createdAt": "2015-07-04T00:59:16Z",
  "updatedAt": "2017-06-18T23:34:00Z",
  "color": "#C679FF",
  "icon": "https://lc-gold-cdn.xitu.io/d83da9d012ddb7ae85f4.png",
  "background": "",
  "showOnNav": true,
  "relationTagId": "",
  "alias": "backend houduan",
  "isCategory": true,
  "entryCount": 19840,
  "subscribersCount": 295562,
  "isSubscribe": false
},

全站文章抓取

将会采集全站所有标签下面的所有文章,采集过程会因为网速和机器性能表现出差异,请各位耐心等待采集完成

这一步采集的数据非常重要,是后面所有分析的基础

采集到的文件会存放在 src/assets/articleData 下面,包含有很多 json 文件,每个文件包含这个标签下的所有专栏文章元信息

npm run allTagData

数组中每个对象

{
  "collectionCount": 5, // 点赞数
  "userRankIndex": 5.4006856695164,
  "buildTime": 1565582852.8327,
  "commentsCount": 2, // 评论数
  "gfw": false,
  "objectId": "5d40d29d518825221b4cbb40",
  "checkStatus": true,
  "isEvent": false,
  "entryView": "",
  "subscribersCount": 0, // 无用
  "ngxCachedTime": 1565627197,
  "verifyStatus": true,
  "tags": [
    {
      "ngxCachedTime": 1565627193,
      "ngxCached": true,
      "title": "React.js",
      "id": "555e99ffe4b00c57d99556aa"
    }
  ],
  "updatedAt": "2019-08-12T04:07:32.818Z",
  "rankIndex": 0.005346156248974,
  "hot": false,
  "autoPass": false,
  "originalUrl": "https://juejin.im/post/5d3ef3646fb9a06b1b1999fd", // 文章的 url
  "verifyCreatedAt": "2019-07-31T01:36:14.238Z",
  "createdAt": "2019-07-31T01:36:14.238Z",
  "user": {
    "community": {
      "weibo": { "uid": "5345591282", "nickname": "岁月痕迹A88" },
      "wechat": {
        "avatarLarge": "http://thirdwx.qlogo.cn/mmopen/vi_32/cabLXAUXiavVhiaDh2050AOOEToUvnZTWsSNqqKZC4hzPzHABC7fxwv6VxwebIxfKdaRkYDZoic8UXfonLDyiafuiaw/132"
      },
      "github": {
        "username": "lxfriday",
        "avatarLarge": "https://avatars0.githubusercontent.com/u/20264467?v=4",
        "uid": "20264467"
      }
    },
    "collectedEntriesCount": 154, // 用户给别人点的点赞数
    "company": "xxx", // 公司
    "followersCount": 35, // 被关注数
    "followeesCount": 70, // 关注数
    "role": "guest", // 用户角色
    "postedPostsCount": 19, // 发布的专栏数
    "level": 2, // 用户等级
    "isAuthor": false,
    "postedEntriesCount": 2, // 分享数?
    "totalCommentsCount": 16, // 总评论数
    "ngxCachedTime": 1565627197,
    "viewedEntriesCount": 1347, // 查看的文章数
    "jobTitle": "前端", // 工作:前端
    "subscribedTagsCount": 166, // 关注的标签数
    "totalCollectionsCount": 120, // 总点赞数
    "username": "云影sky", // 用户名
    "avatarLarge": "https://user-gold-cdn.xitu.io/2019/7/14/16bf1155693d96c2?w=570&h=488&f=png&s=312610",
    "objectId": "57a0c28979bc440054958498" // 用户 id
  },
  "author": "",
  "screenshot": "https://user-gold-cdn.xitu.io/2019/7/29/16c3e3d979a96831?w=1097&h=573&f=png&s=58239",
  "original": true,
  "hotIndex": 21.2095,
  "content": "给 PureComponent 重新指向构造函数之后,_assign 复制对象属性时, Component 构造函数不会覆盖 PureComponent 构造函数,看下面的例子就明白了。 把 PureComponent 变成 Component,userInfo 可正常变化。",
  "title": "React 源码系列-Component、PureComponent、function Component 分析",
  "lastCommentTime": "2019-08-03T16:53:20.577Z",
  "type": "post",
  "english": false,
  "category": {
    "ngxCached": true,
    "title": "frontend",
    "id": "5562b415e4b00c57d9b94ac8",
    "name": "前端",
    "ngxCachedTime": 1565627098
  },
  "viewsCount": 267, // 浏览量
  "summaryInfo": "经过 处理之后,三个组件的区别就是 type 不一样了 和 看不懂可以看下这篇文章 https://www.zhihu.com/question/34183746 js 中 和 的区别和关系 函数的 属性对象上的 是不可枚举的,所以下面两句 给 PureComponent 重新指向构造函数之后, ...",
  "isCollected": false
}

在标签下发表过专栏的用户计算

在标签下发表过专栏的用户计算

npm run userData

脚本执行完成会产生多个 ${number}-userData.json 文件

  • src/assets/userData/${number}-userData.json 多个 json 文件是所有用户的开放信息,用来计算日变化量

关注量排行

获取站内浏览量

npm run follower

脚本执行完成会产生两个文件

  • src/assets/calcUserRank/用户followerRank.json 是排行后的元信息
  • src/assets/calcUserRank/用户followerRank.md 按排名编排的 md 文档

点赞排行

获取站内点赞排行

npm run dianzan

脚本执行完成会产生两个文件

  • src/assets/calcDianzanRank/点赞rank.json 是排行后的元信息
  • src/assets/calcDianzanRank/点赞rank.md 按排名编排的 md 文档

例子

全站文章浏览量排行

获取站内浏览量

npm run view

脚本执行完成会产生两个文件

  • src/assets/calcViewRank/浏览量rank.json.json 是排行后的元信息
  • src/assets/calcViewRank/浏览量rank.json.md 按排名编排的 md 文档

全站文章评论量排行

获取站内浏览量

npm run comment

脚本执行完成会产生两个文件

  • src/assets/calcCommentRank/calcCommentRank.json 是排行后的元信息
  • src/assets/calcCommentRank/calcCommentRank.md 按排名编排的 md 文档

自动分析 uidfile 算法处理后的数据分布状况

自动分析 uidfile 算法处理后的数据分布状况

npm run uidfile

脚本执行完成会产生一个文件

  • src/sitedata/uidfile/uidfile.md 分布状况文档

自动生成当日 website 网站图形数据

自动生成当日 website 网站图形数据

npm run sitedata

脚本执行完成会产生 50+个文件

  • website/public/data/${yeardate}/${0-49}.json 当日的统计数据,50 个文件,经过 uidfile 算法处理形成的文件名
  • website/public/data/${yeardate}/userCount.txt 处理到的总用户数

${0-49}.json 文件结构

{
  "5a66dff2f265da3e4f0a4f1b":[4966,4430,140],  // ...
}
// 关注者,总点赞量,总评论量
// [user.objectId]: [followersCount, totalCollectionsCount, totalCommentsCount]

技术解析

  • async 并发控制
  • chalk 多彩命令行
  • request 发送 http 请求
  • request-promise 把 request promise 化,方便使用 async

项目辅助工具 dev assistant

  • commitlint 规范 commit message
  • eslint 大家都懂
  • prettier 自动格式化代码
  • husky 提供 git 钩子
  • lint-staged 只对当前变动的文件执行格式化和 eslint 校验
  • jest 测试排序算法正确性

前 1000、前 5000 在 20w 条数据中是如何计算的

构建小顶堆,不断往堆中添加数据,比堆顶小的直接抛弃,比堆顶大的,替换成堆顶并对二叉树进行调整,维持小顶堆。遍历所有数据之后 小顶堆就是我们要的所有最大值排行,再对这个数组排序依次就可以获取排名了!!!

// 最小值上浮
function heapify(arr, len, i, compareVal) {
  let min = i
  const l = 2 * i + 1
  const r = 2 * i + 2

  if (l < len && compareVal(arr[l]) < compareVal(arr[min])) min = l
  if (r < len && compareVal(arr[r]) < compareVal(arr[min])) min = r

  if (min !== i) {
    swap(arr, i, min)

    heapify(arr, len, min, compareVal)
  }
}

/**
 * 对 target 建堆
 * @param {array} target 堆数组
 * @param {*} compareVal 从 dataUnit 对象获取比对值
 */
function createHeap(target, compareVal = v => v) {
  for (let i = Math.floor((target.length - 1) / 2); i >= 0; i--) {
    heapify(target, target.length, i, compareVal)
  }
}

function findMaxPrev(dataUnit, target, compareVal = v => v) {
  if (compareVal(dataUnit) > compareVal(target[0])) {
    target[0] = dataUnit
    heapify(target, target.length, 0, compareVal)
  }
}

排行

浏览量排行

👀 浏览量,📌 标签

点赞量排行

👍 点赞数,📌 标签

'掘金' === '前端社区' ????

评论量排行

🐶 评论数,📌 标签

分析的内容就是这些了,我还统计了掘金站内的总的文章数和在标签下发布文章的用户总数

  • 掘金站内去重后总的文章数:10w 左右,可能统计有很大误差,去重前是 20+w
  • 标签下发布文章的用户总数:1.5w 左右

看看 npm scripts 开始玩耍吧

npm run all 一行命名抓取数据分析全流程走完,整个流程处理的数据量比较大,需要半个小时左右

"scripts": {
    "all": "npm run tagList && npm run allTagData && npm run dianzan && npm run view && npm run comment && npm run follower",
    "start": "npm run tagList",
    "tagList": "TASK=tagList node App.js",
    "allTagData": "TASK=allTagData node App.js",
    "composeArticleData": "TASK=composeArticleData node App.js",
    "userData": "TASK=userData node App.js",
    "dianzan": "TASK=dianzan node App.js",
    "view": "TASK=view node App.js",
    "comment": "TASK=comment node App.js",
    "follower": "TASK=follower node App.js",
    "lint": "eslint .",
    "test": "jest"
},

最后欢迎大家关注我的 github 和 微信公众号

juejin-spider's People

Contributors

dependabot[bot] avatar lxfriday avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

juejin-spider's Issues

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.