내 velog 총 조회수 확인하기

비얌·2023년 6월 26일
60
post-thumbnail
post-custom-banner

🧹 개요

현재 이 블로그 플랫폼인 velog(https://velog.io)는 각 게시물의 조회수는 공개하고 있지만(게시물-통계-전체에서 확인 가능) 총 조회수는 공개하고 있지 않다.

하지만 최근 총 조회수를 확인해야 할 일이 생겨 velog의 총 조회수를 구해보기로 했다.

이를 위해 세가지 방법을 썼고, 마지막 방법에서 성공했다.

  1. 인터넷에 공개된 velog 총 조회수 툴 이용하기

  2. selenium으로 크롤링하기

    • selenium으로 velog에 로그인 후 각 게시물의 조회수를 크롤링하려고 했지만 실패했다.
  3. HTTP Request, Response

    • API에 요청을 보내고 응답받은 데이터를 기반으로 내 velog 총 조회수를 알아내는데 성공했다.

이 포스팅에서는 성공한 세번째 방법을 살펴보려고 한다.



✨ 결과 미리보기

지금까지 내가 쓴 총 99개 게시물들의 조회수를 구할 수 있었고, 실제 조회수와 일치하는 것도 확인했다.

그리고 이들의 합을 구하여 총 조회수(45360번)를 구할 수 있었다🥳



🛫 과정

(1) 조회수 데이터를 받아오는 API 확인하기

먼저 조회수 데이터를 받아오는 API를 찾아야 한다. 이곳에 Request를 보내 받은 Response로 조회수를 확인할 것이기 때문이다.

  1. 로그인하고 내 velog 들어가기
  2. 게시글 아무거나 클릭하기
  3. 개발자도구 - Network 들어가기
  4. 왼쪽 위의 clear 버튼을 눌러 로그 지우기
  5. 그 상태에서 '통계' 클릭하기
  6. 개발자도구를 통해 네트워크 로그에 찍힌 graphql을 클릭한다.(혹시 graphql이 안보인다면 창을 끄고 다시 하다보면 보일 수 있다.)

이 graphql이 뭔지 확인해보자. graphql 클릭 후 Headers에 가보면 Request URL에 https://v2cdn.velog.io/graphql 가 보인다. 이곳에 Request를 보내서 데이터를 받아오는 것임을 알 수 있다.

Response를 클릭해봤다. 이곳에 조회수가 있는 것을 확인했다.

Payload를 클릭해보자. 조회수를 알기 위해 Request를 보낼 때 post_id가 필요하다는 것을 알게 되었다. 즉, 모든 게시물의 post_id를 알아야 한다.

💥 올바른 graphql request 선택하기

만약 graphql을 클릭했는데 위의 사진과 같지 않다면(조회수 데이터가 안보인다면) 다른 request을 클릭한 것이다. Response에 조회수 데이터가 있는 graphql request을 찾아야 한다.

(2) Request Header 자동으로 생성하기(fetch 함수 자동 생성하기)

이제 https://v2cdn.velog.io/graphql에 Request를 보내야 한다. 이때 Header에 Cookie의 refresh_token, access_token이 필요하다. 이는 개발자도구-Application-Cookies에서 확인할 수 있다.

하지만, 이를 직접 Request Header에 넣어서 수작업으로 Header를 작성하지 않아도 되는 방법이 있다.

아까 통계 페이지에서 찾은 graphql request 오른쪽 마우스 클릭 - Copy - Copy as fetch를 하면 쉽고 빠르게 fetch 함수를 작성할 수 있다.

복사한 fetch 함수는 아래와 같다.

fetch("https://v2cdn.velog.io/graphql", {
  "headers": {
    "accept": "*/*",
    "accept-language": "en-US,en;q=0.9,ko;q=0.8",
    "content-type": "application/json",
    "sec-ch-ua": "\"Not.A/Brand\";v=\"8\", \"Chromium\";v=\"114\", \"Google Chrome\";v=\"114\"",
    "sec-ch-ua-mobile": "?0",
    "sec-ch-ua-platform": "\"Windows\"",
    "sec-fetch-dest": "empty",
    "sec-fetch-mode": "cors",
    "sec-fetch-site": "same-site"
  },
  "referrer": "https://velog.io/",
  "referrerPolicy": "strict-origin-when-cross-origin",
  "body": "{\"operationName\":\"GetStats\",\"variables\":{\"post_id\":\"2408eec9-f895-4ab5-a9...생략\"},\"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\"}",
  "method": "POST",
  "mode": "cors",
  "credentials": "include"
});

보면 access_token이나 refresh_token에 대한 정보가 없다. 이를 가능하게 해주는 것은 "credentials": "include" 속성인데, 이에 대한 설명은 mdn 문서모던 자바스크립트 튜토리얼에서 확인할 수 있다.

여기에 받아온 값을 콘솔로 찍어보기 위해 마지막에 .then(response => response.json()).then(json => console.log(json))을 추가한다. 이를 콘솔에 찍어보면 아래와 같이 해당 post_id를 가진 게시물의 조회수를 얻을 수 있다!!

💥 만약 코드가 잘못되지 않았는데도 오류가 발생한다면

구글 기본 페이지에서 콘솔을 찍어서일 수도 있다. 이유는 정확히 모르겠지만 지금까지 특별한 이유 없는 콘솔 오류가 발생했을 때 구글 기본 페이지가 아닌 다른 곳에서 보면 해결된 경우가 있었다.

(3) 모든 게시물의 post_id 구하기

자신의 블로그 메인 페이지(들어가자마자 보이는 페이지)에서 개발자도구-Network를 클릭한 후 새로고침하면 아까와 같은 graphql을 확인할 수 있는데, 그걸 클릭한 후 Response 탭을 보면 id를 포함한 모든 포스팅 정보가 들어있는 것을 볼 수 있다.

모든 포스팅의 id를 추출하기 위해, 이 Response를 복붙해서 postData라는 변수에 넣어주고 map 함수로 id만을 추출했다.

const postData = {
    "data": {
        "posts": [
            {
                "id": "2408eec9-f895-4ab5-376d...",
                "title": "[퀴즈앱] 컴퓨터 상식 퀴즈앱 만들기",
                "__typename": "Post"
            },
            {
                "id": "15b28641-c8cc-47a0-d304...",
                "title": "패턴 바꾸기 & 5월 회고",
                "__typename": "Post"
            },
          ...
        ]
    }
};

const postIdArray = postData.data.posts.map(post => post.id)
console.log(postIdArray)

(4) 총 조회수 구하기

post_id를 차례대로 바꿔가서 요청을 보내고, 조회수를 받아온다. 그리고 그걸 더해서 totalSum을 구한다.

const postIdArray = ["2408eec9-f895-4ab5-a9ea-376...", "b43d47b8-a96b-4c91-9fe1-7e5...", ...]

const fetchPromises = postIdArray.map(postId => {
  const requestBody = {
    operationName: "GetStats",
    variables: {
      post_id: postId
    },
    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"
  };

  return fetch("https://v2cdn.velog.io/graphql", {
    headers: {
      accept: "*/*",
      "accept-language": "en-US,en;q=0.9,ko;q=0.8",
      "content-type": "application/json",
      "sec-ch-ua": "\"Not.A/Brand\";v=\"8\", \"Chromium\";v=\"114\", \"Google Chrome\";v=\"114\"",
      "sec-ch-ua-mobile": "?0",
      "sec-ch-ua-platform": "\"Windows\"",
      "sec-fetch-dest": "empty",
      "sec-fetch-mode": "cors",
      "sec-fetch-site": "same-site"
    },
    referrer: "https://velog.io/",
    referrerPolicy: "strict-origin-when-cross-origin",
    body: JSON.stringify(requestBody),
    method: "POST",
    mode: "cors",
    credentials: "include"
  })
  .then(response => response.json())
  .then(json => json.data.getStats.total);
});

Promise.all(fetchPromises)
  .then(results => {
    console.log(results)
    const totalSum = results.reduce((acc, val) => acc + val, 0);
    console.log("Total sum:", totalSum);
  });


✨ 결과

잘 받아와졌다!🥳🥳



🐹 회고

총 조회수를 구하는 방법으로 크롤링밖에 생각 못했어서 이 방법으로 문제를 해결할 거라고는 생각도 못했다(처음에 Request를 보내는 것에 대해 하나도 알지 못했음)

하지만 이렇게 해결하게 되어서 신기하다! HTTP Request/Response에 대해 조금 알게된 것 같아 기쁘다. 앞으로 관련 지식을 더 쌓고 싶다.

참고로 이번 포스팅이 velog 100번째 포스팅이다! 아끼는 글이 100개가 되었다니 뿌듯하고 행복하다😆

profile
🐹강화하고 싶은 기억을 기록하고 공유하자🐹
post-custom-banner

12개의 댓글

comment-user-thumbnail
2023년 7월 2일

피드에서 와 같이 Post get all을 해주는 graphql 사용하시면 한 번에 100개까지 가져올 수 있어서 id 추출하기 더 편하실 것 같아요!

        "query": """query Posts($cursor: ID, $username: String, $temp_only: Boolean, $tag: String, $limit: Int) {
            posts(cursor: $cursor, username: $username, temp_only: $temp_only, tag: $tag, limit: $limit) {
                id
                title
                short_description
                thumbnail
                url_slug
                released_at
                updated_at
                comments_count
                tags
                is_private
                likes
                __typename
            }
        }""",
        "variables": {"username": user_name, "tag": None, "cursor": "", "limit": limit},
        "operationName": "Posts",

혹시 아래 게시글 처럼, 조회수 분석 관련 코드 공유드릴까요!
https://velog.io/@qlgks1/%EB%A6%AC%EB%B7%B0-velog-%EA%B8%B0%EC%88%A0-%EB%B8%94%EB%A1%9C%EA%B7%B8-2%EB%85%84-%ED%9B%84%EA%B8%B0-self-celebration

곧 repo로 하나 파려고하는데,, 아직 정리 하는 중이라 :')...

1개의 답글
comment-user-thumbnail
2024년 3월 4일

네이버 블로그는 게시물 조회하는 방법이없을까요?

답글 달기
comment-user-thumbnail
2024년 5월 19일

옹 대단하십니다

답글 달기
comment-user-thumbnail
2024년 10월 17일

저처럼 벨로그 조회수 탐구하신분이 또 있으셨군요 반갑네요
참 .. 기능 좀 만들어주지 ㅠ
제 벨로그에 해당 방법으로 총 조회수를 매일 계산해서 자동으로 Github 프로필 README에 업데이트 하는 방법 포스팅 했는데 구경오십시오!

https://velog.io/@isntkyu/Github-%ED%94%84%EB%A1%9C%ED%95%84%EC%97%90-Velog-%EC%A1%B0%ED%9A%8C%EC%88%98-%EC%9E%90%EB%8F%99-%EC%97%85%EB%8D%B0%EC%9D%B4%ED%8A%B8-%ED%95%98%EA%B8%B0

답글 달기