# 배경

 오늘 반나절은 정말 끔찍했다. 10to5 동안 듣는 실시간 강의가 나를 무아지경으로 이끌었다. 평소에 나는 일부러 말을 느리게 하냐는 얘기를 듣는 편인데, 강사님이 말하는 속도가 나보다 두 배는 느렸기 때문에 지쳤었다. 그리고 강사님의 발성 이슈인지, 마이크 음질 이슈인지 전달이 거의 안 됐다. 영어 강의를 자막 없이 듣는 것처럼, 말씀하시는 내용이 하나의 문장이 아니라 띄엄띄엄 몇 개의 단어로만 귀에 들어왔다. 기본 문법조차 잘 모르는 언어인데, 무지성 클론 코딩만 하며 강의 시간을 버텼다.

 그러던 중 점심시간에 메일을 확인해 보는데, 자료구조 교수님께서 전체 메일로 이번 학기의 목표가 섞인 말씀을 보내오셨다. 학기 중에 내주실 과제가 내가 익히 들어왔던 것보다 더 많은 것 같아 심장이 쪼렸다. 다행히 먹던 밥이 체하는 일은 없었다. 학교 온라인 교육 플랫폼 plato 에 공지사항이니 동영상이니 하나둘 올라오는걸 보니, 방학이 끝나간다는 사실이 한 자릿 수 d-day보다 더 실감나게 다가왔다. 그런데 이렇게 반나절을 무지성으로 보내고 있다는 걸 자각하니 기분이 끔찍했다.

 5to9 동안 진행되는 실시간 강의 에서는 오늘 웹 스크래핑을 배웠다. 이 강의는 아무리 무미건조한 상태로 들어도 재미있게 들을 수 있어서 좋다. 아무튼 이때 배운 웹 스크래핑 방법을 이용해서, 티스토리와 관련된 무언가를 해보고 싶어졌다.

 

# 이 프로그램의 가치

 저번 학기에 규칙적인 생활 패턴의 중요성을 깊이 체감했었다. 몇 시간 못 자고 시험을 치거나, 잠을 못 참아서 결석을 하거나.. 뼈아픈 실수들이었다. 물론 그 깨달음이 무색하게 지난 방학동안 아주 버라이어티한 수면 패턴으로 살아왔던 것 같다. 이 프로그램으로 내가 어느 시간대에 티스토리를 많이 하는지 확인해 보고, 새벽 시간에 많이 했다면 앞으로 경각심을 가질 수 있다는 점에서 의미가 있다.

 

# 소스 코드

# BeautifulSoup4, Selenium 라이브러리 설치 필요 
# Chrome driver 설치 필요


# 필요한 모듈 호출
import requests
import time
import pandas as pd
from matplotlib import pyplot as plt
from bs4 import BeautifulSoup
from selenium import webdriver


# selenium 실행 옵션 (두 argument 중 택 1)
options = webdriver.ChromeOptions()
# options.add_argument('headless') # 화면을 띄우지 않고 백그라운드에서 진행할 경우
options.add_argument('window-size=1920x1080') # 일정 크기의 화면을 띄우고 진행할 경우


# 데이터를 가져올 웹 페이지 주소
my_tistory_url = 'https://star-sein.tistory.com/'


# selenium 이 제어할 chrome 을 실행
driver = webdriver.Chrome("/###/####/###/chromedriver", options= options) 
# " " 안에 chromedriver 파일의 경로를 넣는다


# 데이터를 수집할 페이지로 이동
driver.get(my_tistory_url)


# 페이지의 html 코드를 저장
my_tistory_html = driver.page_source


# html 형식에 맞춰 파싱(parsing: 추후 이용하기 쉽도록 쪼개기)
my_tistory_soup = BeautifulSoup(my_tistory_html, 'html.parser')


# 게시글 업로드 시간이 들어갈 빈 리스트 생성
my_upload_times = []


# 업로드 시간 정보를 수집하고 페이지 하단의 NEXT 버튼을 누르기를 반복
while True:
    my_tistory_html = driver.page_source
    my_tistory_soup = BeautifulSoup(my_tistory_html, 'html.parser')
    dates = my_tistory_soup.select('div.date')
    
    for i in range(len(dates)):
        str_dates = list(dates[i].stripped_strings)[0]
        my_upload_times.append(list(str_dates)[-5:])
        
    try: # class 이름이 '.next.no-more-next' 인 객체가 있을 경우 반복을 중단한다
        driver.find_element_by_css_selector('.next.no-more-next')
        break
    except Exception: # 반복을 계속한다
        driver.find_element_by_css_selector('.next ').click()
        time.sleep(1)


# selenium 이 제어하는 chrome 을 종료
driver.quit()


# "년-월-일 시:분" 중 '시'만 slicing 해서 counting array 에 빈도 수를 저장 
for i in range(len(my_upload_times)):
    my_upload_times[i] = ''.join(my_upload_times[i])

list_time_count = [0 for i in range(24)]
for i in range(len(my_upload_times)):
    hour = int(my_upload_times[i][:2])
    list_time_count[hour] += 1


# counting array 를 인덱스명이 있는 Series 형태로 변환
s_times = pd.Series(list_time_count, index=[f'{i}~{i+1}' for i in range(24)])


# Series 를 막대 그래프로 시각화
plt.figure(figsize=(16,5))

x = s_times.index
y = s_times.values
plt.xlabel('Time')
plt.ylabel('Counts')
plt.bar(x, y, color='limegreen')
plt.xticks(rotation=45)

plt.show()

# 결과물

역시 새벽 시간에 몰려 있다. 차트의 오른쪽 막대도 높이 세워서 균형을 좀 맞춰야 겠다. 물론 이 글 다음 글부터..

 

# 오늘 처음 해본 것

처음으로 웹 페이지의 개발자 도구를 켜서 html 소스를 다루는 코딩을 해 봤다.
페이지 넘김(NEXT)를 넘기기 위한 조건을 찾고, 코드로 구현하느라 짱구를 되게 많이 굴렸다. 마지막 페이지에 이르러 NEXT가 클릭해도 반응이 없는 버튼이 되었음에도 class 이름이 next 인 객체가 존재하는 점 때문에, 페이지 넘김 중단 조건을 설정하기가 단순하지 않았다.

 

처음으로 만들어 본 매크로 프로그램이라고 할 수 있을까? 지연 시간을 1초로 설정했는데에도 손 떼고 보고 있으면 참 놀랍다. 수작업으로 한다면 스크롤 열심히 내리면서 업로드 시간을 다 기록해야 할 텐데 말이다.

# 한 줄 후기

 쪼렸던 심장이 활기차게 뛸 수 있었던 시간

+ Recent posts