[NodeJs] 벨로그 전체 게시글 조회수 통계 API 만들어봄
벨로그에서는 본인 게시물의 조회수 통계를 볼 수 있는데
타인의 통계는 당연히 안되겠지만
내 전체 게시물 통계가 궁금해서 가끔 확인할려고 앱을 하나
만들어봄
(나중에 날짜 별 포스트별 조회수로 정리좀 해야지)
https://github.com/isntkyu/velog-total
API IO 탐색 (PostMan 사용)
- 개발자 도구를 켠다 (F12)
 
기본적으로 통계를 찾아가기 위한 모든 url은
Request URL: https://v2.velog.io/graphql
이거다 (method : POST)
그리고 request payload 를 달리해서 API 를 호출함
- 그리고 중요한건 Request header에 쿠키가 꼭 필요함
 

이 토큰이 있는 쿠키 값을 그냥 복붙해서 쓰기로 하자
(싸그리 뒤져보았으나 저거를 내 로컬에서 생성할 힌트는 없었다.)
(참고로 이 토큰은 만료되지 않아서 계속 쓰면됨)
내 게시글 > 통계 를 받아올 때
Request Payload :
{ "operationName":"GetStats", "variables":{ "post_id": }, "query":"query GetStats($post_id: ID!) {\n getStats(post_id: $post_id) {\n total\n count_by_day {\n count\n day\n __typename\n }\n __typename\n }\n}\n" }
RESPONSE :
{ "data": { "getStats": { "total": 3, "count_by_day": [ { "count": 1, "day": "2022-02-15T00:00:00.000Z", "__typename": "ReadCountByDay" }, { "count": 2, "day": "2022-02-09T00:00:00.000Z", "__typename": "ReadCountByDay" } ], "__typename": "Stats" } } }
직접적으로 통계를 얻는 호출이다.
postId 를 이용해서 total 조회수를 얻는거지 
그러면 ? 모든 포스트의 postId 값을 전부 모으면 되겠네
Request Payload :
{ "operationName":"Posts", "variables":{ "username":`isntkyu`, "tag":null }, "query":"query Posts($cursor: ID, $username: String, $temp_only: Boolean, $tag: String, $limit: Int) {\n posts(cursor: $cursor, username: $username, temp_only: $temp_only, tag: $tag, limit: $limit) {\n id\n title\n short_description\n thumbnail\n user {\n id\n username\n profile {\n id\n thumbnail\n __typename\n }\n __typename\n }\n url_slug\n released_at\n updated_at\n comments_count\n tags\n is_private\n likes\n __typename\n }\n}\n" }
REPONSE BODY :
{ "data": "posts": [] }
post 배열을 JSON 파싱하면 모든 포스팅의 대한 정보가 온다
(postId를 포함)


포스팅 개수도 일치한다.
---
이젠 postId 배열을 
let postIds = posts.map(post => post.id)
추출해서 반복문으로 위의 통계를 누적시키면 해결~
여기서 비동기 async 라이브러리의
waterfall, whilest 를 사용해서 비동기 처리 비동기 반복문을 사용했다.
[비동기 반복문 사용법]
기본 로직
async.waterfall([
        function(callback) { //태그 다 가져오기
            got.post("https://v2.velog.io/graphql", {
                headers: {
                   cookie: accessToken
                },
                json: {
                    "operationName":"Posts",
                    "variables":{
                        "username":`${userName}`,
                        "tag":null
                    },
                    "query":"query Posts($cursor: ID, $username: String, $temp_only: Boolean, $tag: String, $limit: Int) {\n  posts(cursor: $cursor, username: $username, temp_only: $temp_only, tag: $tag, limit: $limit) {\n    id\n    title\n    short_description\n    thumbnail\n    user {\n      id\n      username\n      profile {\n        id\n        thumbnail\n        __typename\n      }\n      __typename\n    }\n    url_slug\n    released_at\n    updated_at\n    comments_count\n    tags\n    is_private\n    likes\n    __typename\n  }\n}\n"
                }
            }).then(response => {
                // console.log(JSON.parse(response.body).data.posts)
                let posts = JSON.parse(response.body).data.posts
                let postIds = posts.map(post => post.id)
                // console.log(postIds)
                callback(null, postIds);
            })
        },
        function(arg1, callback) { // 태그이름 담기
            let postsLength = arg1.length
            console.log("post s Length: ", postsLength)
    
            let count = 0;
            let total = 0;
            async.whilst(
                function test(cb) { cb(null, count < postsLength); },
                function iter(callback) {
                    got.post("https://v2.velog.io/graphql", {
                        headers: {
                            cookie: accessToken
                        },
                        json: {
                            "operationName":"GetStats",
                            "variables":{
                                "post_id":`${arg1[count]}`
                            },
                            "query":"query GetStats($post_id: ID!) {\n  getStats(post_id: $post_id) {\n    total\n    count_by_day {\n      count\n      day\n      __typename\n    }\n    __typename\n  }\n}\n"
                        }
                    }).then(response => {
                        count++;
                        let result = JSON.parse(response.body)
                        console.log(result)
                        let view = result.data.getStats.total
                        total += view
                        // console.log(to)
                        callback();
                    })
                },
                function (err, n) {
                    console.log("total:", total)
                    callback(null, total);
                }
            );
        },
    ], function (err, result) {
        console.log(result)
        res.send({result:result})
    });
일단 개인적으로 대충 가끔 확인하려고 html 폼을 만들었다.
나만 쓸거기 때문.

아이디랑 쿠키를 복붙해 넣으면 되는데 쿠키
이제 express와 body-parser등으로 app.js 에서
uri를 매핑 시켜봅시다.
app.js
const express = require('express')
const got = require('got')
const app = express()
const async = require('async')
app.use(express.static('public'))
app.listen(3000, function () {
    console.log('connected nodejs')
});
app.get('/', function (req, res) {
    res.sendFile(__dirname + "/public/index.html")
})
// 바디파서
var bodyParser = require('body-parser')
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: true }))
app.post('/search_post', function (req, res) {  
    console.log('POST');
    console.log(req.body);
    let userName = req.body.userId;
    let accessToken = req.body.accessToken;
    async.waterfall([
        function(callback) { //태그 다 가져오기
            got.post("https://v2.velog.io/graphql", {
                headers: {
                   cookie: accessToken
                },
                json: {
                    "operationName":"Posts",
                    "variables":{
                        "username":`${userName}`,
                        "tag":null
                    },
                    "query":"query Posts($cursor: ID, $username: String, $temp_only: Boolean, $tag: String, $limit: Int) {\n  posts(cursor: $cursor, username: $username, temp_only: $temp_only, tag: $tag, limit: $limit) {\n    id\n    title\n    short_description\n    thumbnail\n    user {\n      id\n      username\n      profile {\n        id\n        thumbnail\n        __typename\n      }\n      __typename\n    }\n    url_slug\n    released_at\n    updated_at\n    comments_count\n    tags\n    is_private\n    likes\n    __typename\n  }\n}\n"
                }
            }).then(response => {
                // console.log(JSON.parse(response.body).data.posts)
                let posts = JSON.parse(response.body).data.posts
                let postIds = posts.map(post => post.id)
                // console.log(postIds)
                callback(null, postIds);
            })
        },
        function(arg1, callback) { // 태그이름 담기
            let postsLength = arg1.length
            console.log("post s Length: ", postsLength)
    
            let count = 0;
            let total = 0;
            async.whilst(
                function test(cb) { cb(null, count < postsLength); },
                function iter(callback) {
                    got.post("https://v2.velog.io/graphql", {
                        headers: {
                            cookie: accessToken
                        },
                        json: {
                            "operationName":"GetStats",
                            "variables":{
                                "post_id":`${arg1[count]}`
                            },
                            "query":"query GetStats($post_id: ID!) {\n  getStats(post_id: $post_id) {\n    total\n    count_by_day {\n      count\n      day\n      __typename\n    }\n    __typename\n  }\n}\n"
                        }
                    }).then(response => {
                        count++;
                        let result = JSON.parse(response.body)
                        console.log(result)
                        let view = result.data.getStats.total
                        total += view
                        // console.log(to)
                        callback();
                    })
                },
                function (err, n) {
                    console.log("total:", total)
                    callback(null, total);
                }
            );
        },
    ], function (err, result) {
        console.log(result)
        res.send({result:result})
    });
})
실행 결과

ㅎㅎ
Author And Source
이 문제에 관하여([NodeJs] 벨로그 전체 게시글 조회수 통계 API 만들어봄), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@isntkyu/NodeJs-벨로그-전체-게시글-조회수-통계-API-만들어봄저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
                                
                                
                                
                                
                                
                                우수한 개발자 콘텐츠 발견에 전념
                                (Collection and Share based on the CC Protocol.)