벨로그에서는 본인 게시물의 조회수 통계를 볼 수 있는데
타인의 통계는 당연히 안되겠지만
내 전체 게시물 통계가 궁금해서 가끔 확인할려고 앱을 하나
만들어봄
(나중에 날짜 별 포스트별 조회수로 정리좀 해야지)
https://github.com/isntkyu/velog-total
기본적으로 통계를 찾아가기 위한 모든 url은
Request URL: https://v2.velog.io/graphql
이거다 (method : POST)
그리고 request payload 를 달리해서 API 를 호출함
이 토큰이 있는 쿠키 값을 그냥 복붙해서 쓰기로 하자
(싸그리 뒤져보았으나 저거를 내 로컬에서 생성할 힌트는 없었다.)
(참고로 이 토큰은 만료되지 않아서 계속 쓰면됨)
내 게시글 > 통계 를 받아올 때
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})
});
})
실행 결과
ㅎㅎ