클리앙 모두의공원 게시글 분석기(세번째)

Updated:

이글은 클리앙 모두의공원 게시글 분석기에 이은 세번째 분석기이다. 이번 글에서는 클리앙 모두의공원 게시글의 일 별 조회수/댓글수/공감수 통계를 구해보고자 한다. 조회수/댓글수/공감수를 기반으로 하루동안 이슈를 끌었던 게시물 TOP100 리스트를 만들어 볼 것이다.

1. 도입 - 다시 데이터를 수집하자

첫번째 분석기에서 파이썬 웹 크롤러를 통해서 데이터를 수집했었다. 이 때는 새 글을 등록되면, 랜덤으로 글을 선택해서 1시간 마다 해당 웹페이지를 다시 읽어서 24시간 동안 조회수/댓글수/공감수를 저장하였다. 즉, 모두의 공원 게시물의 등록 후 24시간 동안의 조회수/댓글수/공감수의 추세를 분석하였다.

첫번째 분석기에서 수집한 파이썬 웹 크롤러의 데이터를 토대로 2가지 방향으로 분석을 진행하였고 추가 분석할 내용은 없어 보였다. 그래서 이번에는 데이터 수집부터 다시 시작하였다. 이번 아이디어는 모두의 공원 게시물의 일별 통계를 분석해보고 싶었다. 날짜가 변경되면 전날(어제)의 게시물 통계를 모두 모아서 어디 게시물이 모두의 공원 커뮤니티에서 가장 큰 이슈가 되었는지를 TOP100 리스트를 생성해보고자 한다.

이전에 일별 추천 게시물이나 베스트 게시물 등의 형태로 커뮤니티 글 중에 추천 게시물만 보여주는 웹사이트를 방문해본 적이 있다. 이런 종류의 분석을 목표로 하였다.

이전에 만들었던 파이썬 웹 크롤러를 다시 꺼내왔다. 한번 코드를 작성해두었더니 여러모로 요긴하게 사용하고 있다. 웹 크롤러 동작은 변경할 것이 없으니 데이터 수집 시점과 결과 취합 부분만 변경하면 된다.

GitHub repo11_top100_project 폴더를 추가하여 세번째 분석에 사용한 스크립트와 결과를 업로드 하였다. 관심이 있다면 코드를 같이 확인해보자.

데이터 수집은 01_happen_yesterday.py 스크립트 파일에서 수행하였다. 이번 데이터 수집의 핵심 사항은 모공에 등록되는 모든 게시글 정보를 수집해야 하는데 언제 정보를 수집할 것인지가 되겠다. 게시물이 등록되고 어느 정도 시간이 지나야만 조회수/댓글수/공감수를 저장할 수 있는데 이 시간을 얼마로 정하는지에 따라서 취합 데이터가 달라질 수 도 있기 때문이다. 일단 지난 분석기에서 취합했던 데이터를 토대로 너무 짧지도 않고 너무 길지도 않은 6시간으로 선택했다. 게시물 등록 후 6시간이 지나면 유저들의 판단을 받았다고 생각한 것이다.

while keepGoing:
    # Step 1. 게시물 ID 확인
        # a. 날짜로csv 파일명을 확인해서 파일명 존재시 마지막 row의ID 확인
        # b. 파일명이 없을 경우, 현재 게시물의 첫글로 초기화(이제부터 시작)
    thisId = lastId + 1
    print("\nThis id : %d - [%s]" % (thisId, getNowTime()))
    scraper.boardId = thisId

    # Step 2. 확인한 게시물 ID의 +1 게시글을 읽어서 확인
        # a. 정해진 시간(ex. 6hour) 보다 오래되었으면 정보를 csv에 저장
        # b. 정해진 시간을 안넘겼으면 그대로 out 종료
    scraper.scraping()

    ret = scraper.checkLongerThan()
    if ret is None:
        print("Id : %d is HTTPError 404 or was deleted by the web manager.." % thisId)
        httpError = httpError + 1
        if httpError > 30:
            print("httpError count is  %d. We're going out." % httpError)
            keepGoing = False
    elif ret:
        print("Id : %d is longer than buzzCheckDuration." % thisId)
        scraper.concatPd()
        httpError = 0
    else:
        print("Id : %d is short than buzzCheckDuration." % thisId)
        keepGoing = False

    lastId = thisId

스크립트의 메인 로직 부분이다. 모공의 게시물 id가 신규 등록글에는 +1이 되어서 할당됨을 이용했다. 게시물 id를 기반으로 웹 크롤링을 수행하고 해당 페이지가 존재하지 않으면 스킵, 기준 시간인 6시간이 넘었으면 데이터 저장 후 다음 게시물을 웹 크롤링 수행, 기준 시간인 6시간이 안되었으면 스크립트 종료를 수행한다.

이 스크립트를 1분 단위로 계속 실행해주면 게시물 등록 시간을 기준으로 6시간이 넘으면 바로바로 정보 수집을 해서 default.csv 파일에 계속 저장하게 된다.

2. 수집 데이터 가공 & 수치화

데이터 수집은 default.csv 파일에 계속 추가된다. 날짜가 변경되고 6시간이 지나면(매일 6AM) 전날의 데이터 수집이 완료되므로 데이터 가공 및 수치화를 할 수 있다.

데이터 가공은 02_build_data.py 스크립트에서 수행한다.

$ python3 02_build_data.py default.csv

날짜가 변경되고 위와같이 csv 파일을 인자로 넣어서 실행하면 csv 파일 데이터 중에 전날 날짜에 해당하는 데이터만 추출하여 results 폴더로 이동시킨다.

이제 가공을 해야하는 데이터가 모두 확정된 상태가 된 것이다. 이제 데이터 별로 순위를 매겨서 TOP100 리스트만 추출하면 된다. 처음에는 조회수/댓글수/공감수 별로 TOP100 리스트를 생성하려고 했다. 하지만 이 방법에는 보여줘야할 리스트가 3가지 종류로 너무 많아지고 각 항목별 TOP100 리스트에는 서로 중복되는 게시물이 너무 많았다. 그래서 조회수/댓글수/공감수를 합쳐서 수치화하고 이를 Buzz라고 이름을 붙였다. 아래는 스크립트에서 Buzz를 계산하는 부분이다.

sum_view = (int)(sum[ ['view'] ].iloc[0].values)
pd_sum_pct= pd.DataFrame(ystDf['view'].apply(lambda x: x/sum_view))
pd_sum_pct.columns = ['view_pct']

sum_reply = (int)(sum[ ['reply'] ].iloc[0].values)
pd_sum_reply = pd.DataFrame(ystDf['reply'].apply(lambda x: x/sum_reply))
pd_sum_reply.columns = ['reply_pct']
pd_sum_pct = pd.concat([pd_sum_pct, pd_sum_reply], axis=1)

sum_symph = (int)(sum[ ['symph'] ].iloc[0].values)
pd_sum_symph = pd.DataFrame(ystDf['symph'].apply(lambda x: x/sum_symph))
pd_sum_symph.columns = ['symph_pct']
pd_sum_pct = pd.concat([pd_sum_pct, pd_sum_symph], axis=1)

pd_sum_pct = (pd.DataFrame(pd_sum_pct.sum(axis=1)))
pd_sum_pct = pd_sum_pct.apply(lambda x: (x/3*100))
pd_sum_pct.columns = ['buzz_pct']

ystDf = pd.concat([ystDf, pd_sum_pct], axis=1)

largest = ystDf.nlargest(100, 'buzz_pct')[ printLists ]

Buzz는 게시물의 조회수/댓글수/공감수를 각 항목의 총합으로 나눠서 각 게시물의 항목이 가진 수가 그 항목의 총합에서 차지하는 비율을 계산했다. 그리고 3개 항목으로 이뤄졌기 때문에 각 비율을 3으로 나눠서 그 총합이 100%가 되도록 하였다.

ID 조회수 댓글수 공감수 Buzz
1 100 0 10 40.00%
2 100 50 0 23.33%
3 100 50 0 23.33%
4 100 0 0 6.67%
5 100 0 0 6.67%
TOTAL 500 100 10 100.00%

위는 설명을 위한 간단한 예시이다. ID 5를 보면 조회수가 100으로 조회후 총합인 500으로 나누면 20%가 된다. 댓글수와 공감수는 0이기 때문에 0%가 된다. 이 결과의 총합인 20%를 3으로 나누면 6.67%가 된다.

이 Buzz가 의미하는 바는 조회수/댓글수/공감수를 기반으로 전날에 등록된 모든 게시물 중에 이 게시물이 얼마나 화제가 되었는지(=이목을 끌었는지)를 보여주는 것이다. 계산된 Buzz 수치를 가지고 상위 100개를 데이터를 뽑으면 완료가 된다.

3. 결과 - 2019월 05월 01일 TOP100

TOP100 리스트가 완성되었다. 데이터를 수집하고 Buzz 수치를 기반으로 TOP100을 추출하면서 다른 사이트에서 보여주는 추천글 내지는 베스트글들이 어떻게 만들어질지 대략 상상할 수 있는 경험이었다.

여기서는 게시물의 조회수/댓글수/공감수를 각 1/3의 동일 비중으로 취급하였지만 어떤 항목값을 얼만큼의 비중을 부여할지는 전적으로 운영자(=코드 작성자) 마음이다. 운영자가 정의한 기준이 제 각기이므로 선정된 베스트글 목록이나 순위가 사이트 별로 다를 것이다.

마지막으로 모두의 공원 게시글의 2019월 05월 01일 TOP100 리스트를 아래에 추가하였다. TOP100 리스트에는 어떤 글들이 있는지 구경해보자.

랭킹 제목 Buzz (%) 조회수 댓글수 공감수
1 (속보) 세월호 특조위, 황교안 조사 결정 1.64 22949 49 328
2 대한민국 역사상 선거제를 단독으로 입법 처리한적은 없습니다. 1.19 17436 71 225
3 임은정 검사의 페북…. 1.11 20192 26 218
4 전우용 교수 트윗 1.02 11264 43 204
5 곰탕집 성추행은 결국 이렇게 끝나네요 0.98 26654 111 152
6 자유한국당의 근성.jpg 0.97 19106 30 186
7 반말하지 마라, 김재원 의원 0.96 18040 54 178
8 오늘자 장도리 0.88 16758 25 170
9 제1차 자한당 해산 집회 공지 떴습니다! 0.85 8695 32 173
10 김정란 교수 ‘황교안은 남자 박근혜다’ 0.77 15670 34 143
11 실종 23년만에 찾은 엄마 0.73 17579 51 126
12 한국인이 반드시 알아야 하는 한국 최고의 주식 고수… ㄷㄷㄷ 0.72 25669 12 127
13 윤석렬 부장검사 징계하고 좌천한게 황교안이군요 -_-; 0.62 9014 24 121
14 박원순, 자한당 천막농성 좌시하지 않겠다. 0.61 6314 27 121
15 문재인 대통령 지지율 51.1%..4.4%P 상승 0.51 6432 24 99
16 오늘자 역대급 장도리..ㅋㅋ 0.45 13715 27 75
17 文, 노동절 작심 메시지 “노동계 이미 주류···투쟁 아닌 상생 필요”.gisa 0.42 6864 19 80
18 파산후,우울증..32살에 4년째 히키 0.38 34683 50 25
19 자유왜구당 해산 청원 130만 돌파 기념 피자 당첨자 발표 0.31 3770 16 60
20 장도리 0502 0.28 4689 10 55
21 검찰총장이 입장내는걸 보면서 공수처 설치 필수네요 0.25 3459 6 51
22 대통령 지지율 4.4% 급상승. 51.1%골든크로스, 20대 급상승 0.25 4527 18 44
23 검찰에 직격탄 날린 검사 “자정능력 전혀 없다” 0.24 4476 4 48
24 이번에 자유당은 역대급으로 자기 발등 찍은 듯 합니다. 0.24 3970 21 42
25 릴레이630일)장충기 삼성공화국과 적폐청산 그날까지!!! 0.23 501 9 50
26 세월호 유가족 측 ‘자유당, 절대로 막겠다’ 0.23 3740 5 45
27 원래 귀여운 이재정 의원의 자유당 폭파 0.22 5328 21 37
28 이것도 20만 갑시다 0.22 3780 21 39
29 소개팅 장소 논란.jpg 0.22 19063 74 0
30 김어준의 생각 ‘중앙일보는 사람들을 바보로 아나 봅니다.’ 0.22 4923 13 39
31 순간포착! 정확히 150만명 청원 순간 0.21 3570 4 42
32 서울시 불허 방침에…한국당 광화문광장 천막당사 무산 0.19 3606 19 33
33 한걸레 근황.jpg 0.19 8423 22 25
34 사나가 여초에서 까이는 이유.gif 0.19 9241 26 22
35 홍영표 ‘자유당, 고발 취하 없다. 보좌진들 중에 욕설, 막말, 폭력만 고발’ 0.19 4358 9 34
36 오만불손한 검찰놈들 0.19 2047 6 38
37 ‘재용이네 분식’.gif 0.19 6020 17 29
38 자한당 해산 청원 1,620,000 돌파 0.19 3079 10 35
39 사나에게 악플남기던 사람들…SNS… 0.18 7675 27 23
40 세월호 특조위, 황교안 조사 결정.gisa 0.18 2449 10 34
41 아침 딸래미 침대 풍경.jpg 0.18 9819 16 22
42 (속보) 자한당 내일 10시 삭발식 예정 0.17 8068 62 8
43 많이들 참여하시라고 끌올합니다. 국회의원 국민소환제 청원 0.16 1460 17 30
44 국회의장 바뀌면 함 보자는 장제원 의원의 육성 협박 to 사무처직원 0.16 3191 13 29
45 문대통령과 이재용의 약속 0.16 4874 17 25
46 검찰총장 입장문을 왜 내는지 이해가.. 0.16 3405 18 26
47 백상 영화부문 대상은 정우성 0.16 4097 26 22
48 저널리즘 토크쇼 J 상타네요 0.16 2175 9 30
49 옆동네 비행기 등받이 논란.txt 0.16 8931 61 3
50 (속보) 자유당 해산 청원 161만 돌파 0.16 3583 14 26
51 한국 검찰의 무소불위 권력 ㄷ ㄷ. jpg 0.15 6757 10 23
52 기자들이 쓴 기사에 책임제를 실시하면 어떨까요? 0.15 1224 85 4
53 나경원이원 전 비서 박창훈씨가 중학생에게 막말과 폭언 논란.기사 0.15 3003 8 28
54 표창원 ‘자유당, 내가 재수 없다고요? 괜찮습니다’ 0.15 3771 10 26
55 베네수엘라 정치 상황 요약 0.15 5390 44 12
56 전 사나 논란 이해 안가네요. 0.15 7044 23 17
57 그냥 징병제 없애버렸으면 좋겠습니다. 0.15 1374 85 3
58 현재 청원 인원.jpg 0.15 5162 12 23
59 문통앞에서 재롱부리는 이재용.jpg 0.15 8109 61 2
60 스티븡 유가 대한민국에 미친 효과 0.15 4403 37 15
61 왜구당 망하게 해주세요 0.14 2375 9 26
62 아키히토 일왕은 반전주의자인데… 0.14 2878 18 22
63 자유당 해산 1,440,000명 돌파~ 0.14 3748 11 23
64 다리가 생겨 기뻐하는 아이.gif 0.14 7240 6 20
65 장제원 아들근황.jpg 0.14 10136 14 13
66 케텔, 하이텔, 천리안, 나우누리, 유니텔 0.13 2424 78 1
67 (속보) 靑·정부· 민주당, 강원도 도민 위해 나섰다. 0.13 2821 2 26
68 20대 남자 현상은 왜 생겼나 (시사인) 0.13 4748 67 1
69 일본 제국주의 추종자 / 일반 일본인, 구분해야.. 0.13 2850 6 24
70 150만 돌파를 보니 생각나는 글귀.jpg 0.13 2480 1 26
71 미더덕의 진실.jpg 0.13 11188 32 4
72 청원글이 다 사라졌네요 1000만 청원 갑시다 0.13 4208 3 23
73 재롱떠는 이재용…….gif 0.13 7559 36 7
74 베네수엘라 근황 0.13 6639 33 9
75 남편은 정말 남의편인가봐요. 0.13 5988 53 3
76 자한당 보좌관 동정심유발 글을 본 감상.jpg 0.13 2755 6 23
77 장제원이 힘을 보태주네요 0.12 4908 18 16
78 특조위 ‘CCTV 9시 30분까지 켜져있었을 것’ 0.12 1838 0 26
79 여성인 나경원 의원의 삭발 동참은 솔직히 너무 심한 거 같습니다. 0.12 5673 5 19
80 자한당 해산 청원 159만 돌파입니다.jpg 0.12 3020 11 20
81 이정미 ‘나경원, 비서가 발판 챙기고 다니더라’ 0.12 4782 13 17
82 베네수엘라 사태에 양비론은 동의 하기 어렵습니다. 0.12 1864 68 2
83 아주 신난 이재용.gif 0.12 7378 26 9
84 자유한국당 정당해산 청원, 추천글에 항상 있었으면 좋겠습니다. 0.12 889 0 26
85 CGV 유감. -_- 영화표 만원씩 주고 산 사람들이 엔딩 크레딧도 못보나요? 0.12 4170 40 8
86 오늘 쉬지 않고 매장 오픈한게 정답이였네요 0.12 6000 27 10
87 879억짜리 구미의 랜드마크.JPG (추가) 0.12 6280 20 12
88 프레임 씌우기에 항상 당해오던 진보진영 0.12 2516 6 21
89 문무일 이 양반, 본색이 드러나는군요. 0.11 4949 14 15
90 나경원,,, 정말 어이가~~~~~~ㅎ 0.11 5940 13 14
91 초저가 코스프레녀.jpg 0.11 13298 8 6
92 내일 삭발하는 자유한국당 의원 라인업.jpg 0.11 6358 46 2
93 수능 만점 2019 서울대 수석 입학생의 클라스.jpg 0.11 5897 35 6
94 피임 하라는데 안하는 남친.jpg 0.11 10121 36 0
95 현재 152만이 넘었습니다 0.11 2903 5 20
96 왜구가 길바닥으로 나가려 할때 문통은.. 0.11 2147 2 22
97 프로그래머 남편.jpg 0.11 10645 22 4
98 내일 삭발식에 여성당원 참석하라는 클라스 0.11 5510 21 11
99 예비역 마법소녀 이현지짱 0.11 4754 15 14
100 스포) 엔드게임에 대한 루소형제의 Q&A.jpg 0.11 3983 47 4


Leave a comment