文章教你如何作掘金站內數據抓取,數據解析,最後造成排序後的排名。前端
0821更新: 掘金總點贊量前 5000 排行發佈 | 掘金總關注量前 5000 排行(20190821)vue
0827更新: 【第三方掘金功能】掘金我的數據統計,第三方實現的掘金用戶 dashboardnode
項目原由是我忽然想看看掘金站內有哪些優質做者,爲了避免錯過每個大佬,我選擇直接抓取站內全部的文章信息找到做者並進行排名。各位關注 + 文章閱讀 一條龍走起!webpack
項目地址 juejin-spider 歡迎 star issueios
掘金 spider 和數據分析,主要關注了下面幾個排行和統計,排行點擊直接查看git
先上掘金前50排名,關注一波???? 前5000排名看這裏程序員
🎉 等級,👦 關注數,🏠公司github
獲取掘金站內全部標籤信息web
npm run tagList
複製代碼
會把標籤信息寫入到 src/assets/tagList/tagList.json
,每一個標籤包含下面的信息,主要是 title
和 id
面試
{
"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 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 文檔async
併發控制chalk
多彩命令行request
發送 http 請求request-promise
把 request promise 化,方便使用 async項目輔助工具 dev assistant
commitlint
規範 commit messageeslint
你們都懂prettier
自動格式化代碼husky
提供 git 鉤子lint-staged
只對當前變更的文件執行格式化和 eslint 校驗jest
測試排序算法正確性構建小頂堆,不斷往堆中添加數據,比堆頂小的直接拋棄,比堆頂大的,替換成堆頂並對二叉樹進行調整,維持小頂堆。遍歷全部數據以後 小頂堆就是咱們要的全部最大值排行,再對這個數組排序依次就能夠獲取排名了!!!
// 最小值上浮
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)
}
}
複製代碼
👀 瀏覽量,📌 標籤
👍 點贊數,📌 標籤
'掘金' === '前端社區'
????
🐶 評論數,📌 標籤
分析的內容就是這些了,我還統計了掘金站內的總的文章數和在標籤下發布文章的用戶總數
看看 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 和 微信公衆號