Youtube API 사용하여 댓글 수집하기.

정명진·2023년 2월 14일
1

어제 전직장에서 만난 동기 형한테 연락이 왔다.
상사가 유튜브에서 자사 제품 댓글을 수집해서 엑셀로 정리하라고 했다고 한다...
그래서 댓글이 몇개냐 물었더니 1200개 정도라고 했다 ㅋㅋㅋ
형은 마케팅 직무여서 개발을 몰랐고...300개쯤 하다가 이건 아니다 싶어서 SOS 요청을 했다고 한다. 딱히 업무가 없던 터라 급작 댓글 수집기를 구현해봤다.

이글은 기본적인 Google API 사용을 위한 준비가 되어 있다는 가정하에 진행합니다.

우선 Google Clould Console 에서 Youtube API 사용을 신청해야 합니다.

그리고 나서 OAUTH를 통한 액세스 토큰 획득에 시도한다.

https://accounts.google.com/o/oauth2/v2/auth?scope=https://www.googleapis.com/auth/youtube.force-ssl&access_type=offline&redirect_uri=${your_redirect_uri}&response_type=code&client_id=${your_client_id}

정보를 채워서 접근 시도를 하면 로그인후 인가코드를 발급해 준다.

이제 인가코드를 이용해 액세스 토큰 발급을 요청한다.

POST https://www.googleapis.com/oauth2/v4/token
form-data
grant_type: authorization_code
code: ${인가코드}
client_secret: ${your_secret}
redirect_uri: ${your_redirect_uri}
client_id: ${your_client_id}

그러면 다음과 같이 결과를 받을 수 있다.

{
    "access_token": ${your_access_token},
    "expires_in": 3599,
    "refresh_token": ${your_refresh_token},
    "scope": "https://www.googleapis.com/auth/youtube.force-ssl",
    "token_type": "Bearer"
}

이제 이 refresh_token을 이용해 access_token을 재발급에 사용할 수 있다. 약 6개월동안 가능.

하지만 우리의 목표는 review를 수집하는것이므로 다음과 같이 요청을 한다.

GET https://www.googleapis.com/youtube/v3/commentThreads?videoId=${수집하려는 비디오 ID}&part=snippet

Bearer ${획득한 액세스 토큰}

비디오 ID는 유튜브 비디오에 들어갔을때 vId=4dsda43123 형식의 문자다. 약 11자리로 기억한다.

요청을 보내면

{
    "kind": "youtube#commentThreadListResponse",
    "etag": "joVbwvn0SYPpWw-OJTk2LGdQ_z4",
    "nextPageToken": "QURTSl9pM1FqX3RVYzRURWZhM2pWVXRCN1Vyd1hneGV5WXhyTWZpX1NsdGpwQ1huenlMWERZYk9FTTVLY3JObUdwd3dwT2lRUkE2QWEwVQ==",
    "pageInfo": {
        "totalResults": 20,
        "resultsPerPage": 20
    },
    "items": [
        {
            "kind": "youtube#commentThread",
            "etag": "oL7ccAc4asluX9lMn0jPRWv7wIc",
            "id": "UgxAQ0eMf8-FDJUoMU14AaABAg",
            "snippet": {
                "videoId": "rS6Ifm_YecQ",
                "topLevelComment": {
                    "kind": "youtube#comment",
                    "etag": "EYEonVUKcQpvYvxWAnH9cEyf1xU",
                    "id": "UgxAQ0eMf8-FDJUoMU14AaABAg",
                    "snippet": {
                        "videoId": "rS6Ifm_YecQ",
                        "textDisplay": "as a korean, this is cool... however, there are thousands and thousands of scammers getting rich and taking advantage of people's insecurities too.  it's sad.",
                        "textOriginal": "as a korean, this is cool... however, there are thousands and thousands of scammers getting rich and taking advantage of people's insecurities too.  it's sad.",
                        "authorDisplayName": "Jeremy C.",
                        "authorProfileImageUrl": "https://yt3.ggpht.com/ytc/AL5GRJWq7AWfcAelqi0IoYWJz01NbEWmqIJ1WRH3hw_uM4U=s48-c-k-c0x00ffffff-no-rj",
                        "authorChannelUrl": "http://www.youtube.com/channel/UCboISnGcAgR6H4EHv3-pJIw",
                        "authorChannelId": {
                            "value": "UCboISnGcAgR6H4EHv3-pJIw"
                        },
                        "canRate": true,
                        "viewerRating": "none",
                        "likeCount": 0,
                        "publishedAt": "2023-02-08T01:06:08Z",
                        "updatedAt": "2023-02-08T01:06:08Z"
                    }
                },
                "canReply": true,
                "totalReplyCount": 0,
                "isPublic": true
            }
        }
    ]
}

이런 형식으로 response를 받게 된다. 하지만 최대 한번에 수집할 수 있는 댓글은 maxResult 파라미터를 설정해도 100개 까지다. 100개 이상의 댓글을 수집할때는 nextPageToken 을 보내 다음 페이지의 댓글을 달라고 요청을 해야한다. 해당 부분을 저는 이렇게 구현했습니다.

private String getNextTokenYoutube(JSONObject parseResult, String nextToken) {
        if(parseResult!=null && parseResult.containsKey("nextPageToken"))
            nextToken = parseResult.get("nextPageToken").toString();
        return nextToken;
    }

그리고 댓글 수집기의 핵심 코드입니다. nextPageToken을 체크하면서 있으면 계속 댓글을 수집하는 로직입니다.

nextToken = getNextTokenYoutube(parseResult, nextToken);
            while(!nextToken.isEmpty()) {
                reviewDetails = getConnectResultByX509(new URL(link +"&pageToken="+nextToken), token);
                parseResult = (JSONObject) parser.parse(reviewDetails);
                JSONArray temp = (JSONArray) parseResult.get("items");
                for (Object item : temp) {
                    JSONObject it = (JSONObject) item;
                    JSONObject snippet = (JSONObject)it.get("snippet");
                    JSONObject topLevelComment = (JSONObject)snippet.get("topLevelComment");
                    JSONObject snippet1 = (JSONObject)topLevelComment.get("snippet");
                    String textDisplay1 = snippet1.get("textOriginal").toString();
                    comments.add(textDisplay1);
                }
                
                nextToken = null;
                nextToken = getNextTokenYoutube(parseResult, nextToken);
                if (nextToken==null)
                    break;
            }

댓글 수집기를 작동하면

idx: 1 comment = as a korean, this is cool... however, there are thousands and thousands of scammers getting rich and taking advantage of people's insecurities too.  it's sad.
idx: 2 comment = every people on screens must have perfect skin in korea.
It leaded to in reality, if skin is not good, can't get anything.
idx: 3 comment = I’d love to get Korean skincare but I don’t know where to buy without having to go online.
.... 생략....
idx: 523 comment = Skin care expert - Oily skin
idx: 524 comment = Korea is really taking the whole damn world🤷‍♀️
idx: 525 comment = What they spend is Half GDP of Africa Continent.
idx: 526 comment = 2 nd 🤘🏼🤘🏼🤘🏼🤘🏼🤘🏼

다음과 같이 결과를 받을 수 있고 댓글 뿐 아니라, 댓글 작성일, 답변 가능여부 등을 알 수 있습니다. 엑셀로 결과를 전환하고 싶은 분들은 엑셀로 저장하는 로직을 만들면 됩니다.

profile
개발자로 입사했지만 정체성을 잃어가는중... 다시 준비 시작이다..

0개의 댓글