본문 바로가기
study

Youtube 댓글 크롤링

by 나는야오리 2020. 4. 5.
목표 : 특정 유투브 채널의 댓글 자동으로 수집하기
1. 준비 사항
2. 크롤링

1. 준비사항

1.1. 필요한 모듈 설치

여기서 가장 중요한 모듈은 selenium, BeautifulSoup 두가지이다. Selenium는 웹앱을 테스트하기 위한 프레임워크이다. 반복적인 크롤링 작업을 대신 해줄 도구라 보면 된다. BeautifulSoup은 HTML 및 XML 문서 구문 분석을 하기위한 Python 패키지이다.

import requests
from bs4 import BeautifulSoup
import time
import urllib.request
from selenium.webdriver import Chrome
from selenium import webdriver
import re     
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.keys import Keys
import datetime as dt
import pandas as pd

1.2. 크롬드라이버

우선 chromedriver를 설치해주어야한다. 아래 사이트에서 본인의 크롬 버젼에 맞는 드라이버를 설치하길 바란다. 크롬드라이버란 우리가 앞으로 해야할 반복적인 작업을 알아서 대신 해줄 또다른 크롬창을 말한다. 댓글을 수집하기 위해 스크롤을 한다던지 다음 영상을 클릭한다던지 그러한 일련의 작업이 chromedriver 상에서 이루어질 것이다.

 

Downloads - ChromeDriver - WebDriver for Chrome

WebDriver for Chrome

chromedriver.chromium.org

1.3. xpath

나는 백선생님 채널의 영상 댓글을 모두 가져오고자 한다. 여기서 핵심은 html 구조에서 내가 원하는 위치를 찾는것이다. 즉 유투브 메인페이지에서 백선생님 채널을 들어가기 위해서는 우선 검색창을 클릭한 후 키워드를 치고 검색버튼을 눌러야한다. 이를 컴퓨터에게 시키기 위해서는 검색창과 검색 버튼의 위치를 정확하게 짚어주어야한다. find_elements_by_xpath() 안에 위치 지정해주면 된다. 예를 들어 검색버튼의 xpath를 알고싶다면 F12를 누르고 개발자도구에서 가장 좌측 상단 마우스 표시를 클릭하여 검색버튼에 가져다대면 된다. 그리고 컬러링된 부분에서 우클릭을 하면 xpath값을 복사할 수 있다.

2. 크롤링

2.1. 크롬 활성화 - 유투브 접속 -> 검색창 클릭 -> 검색어 입력

# 브라우저 드라이버 설정
delay=1 # 딜레이 시간을 준다. 엉뚱한 데이터를 받아올 수도 있으므로
browser = webdriver.Chrome("C:/Users/kjh96/Github/chromedriver.exe") 
browser.implicitly_wait(delay)

start_url  = 'https://www.youtube.com'
browser.get(start_url)  
browser.maximize_window()
browser.implicitly_wait(delay)


# 채널 검색
browser.find_elements_by_xpath('//*[@id="search-input"]')[0].click() # 검색창영역클릭
browser.find_elements_by_xpath('//*[@id="search-form"]/div/div/div/div[2]/input')[0].send_keys("백종원") # 검색창 영역에 원하는 youtuber입력
browser.find_elements_by_xpath('//*[@id="search-form"]/div/div/div/div[2]/input')[0].send_keys(Keys.RETURN) # 엔터


# 채널 선택
browser.find_elements_by_xpath('//*[@class="channel-link yt-simple-endpoint style-scope ytd-channel-renderer"]/div/yt-img-shadow')[0].click()
browser.implicitly_wait(delay)


# 동영상 탭 선택
browser.implicitly_wait(delay)
browser.find_element_by_xpath('//*[@id="tabsContent"]/paper-tab[2]').click()


# 페이지 스크롤 - 스크롤 내려서 전체 동영상 목록 가져오기(예시 20번)
body = browser.find_element_by_tag_name('body') # 스크롤하기 위해 소스 추출
num_of_pagedowns = 10


num_of_pagedowns = 20
while num_of_pagedowns:
    body.send_keys(Keys.PAGE_DOWN)
    browser.implicitly_wait(delay)
    num_of_pagedowns -= 1

2.2 채널 선택 -> 동영상 탭 선택 -> 스크롤을 통해 전체 영상 목록 로드

# html로 파싱
html0 = browser.page_source
html = BeautifulSoup(html0,'html.parser')
html


# 각 동영상 일부 url 추출
video_list = html.find_all('ytd-grid-video-renderer',{'class':'style-scope ytd-grid-renderer'})
video_list


# 각 동영사 url 완성
base_url = "https://www.youtube.com"

url_list = []
for i in range(len(video_list)):
    url = base_url+video_list[i].find('a',{'id':'thumbnail'})['href']
    url_list.append(url)

url_list

2.3. 크롤링

화면 내 표시되는 댓글으 자동으로 긁어오도록하는 코드. 하나씩 천천히 따라하다보면 이해가 될 것이다. 생각보다 간단한 코드 구성이다. 주석으로 설명을 달아놨다.

# 데이터 프레임 만들기
df = pd.DataFrame({'name':[],
                     'thumbnail':[],
                     'view':[],
                     'previous_time':[],
                     'video_url':[],
                     'start_date':[],
                     'comment_num':[],
                     'likes_num':[],
                     'unlikes_num':[],
                     'comment_list':[]
                     })

# 크롬 드라이버 활성화
start_url = 'https://www.youtube.com'
delay = 3
browser = Chrome("C:/Users/kjh96/Github/chromedriver.exe")
browser.implicitly_wait(delay)
browser.get(start_url)  
browser.maximize_window()
time.sleep(1)

# len(url_list) 대신 예시로 5번만
# 추출한 영상 url에서 제목, 썸네일, 링크 등등 메타데이터를 추출한다.
for i in range(0,5):
    name = video_list[i].find('a',{'id':'video-title'}).text
    thum = video_list[i].find('a',{'id':'thumbnail'}).find('img')['src']
    url = base_url+video_list[i].find('a',{'id':'thumbnail'})['href']
    meta0 =video_list[i].find('div',{'id':'metadata-line'})
    view = meta0.find_all('span',{'class':'style-scope ytd-grid-video-renderer'})[0].text.split()[1]    
    previous = meta0.find_all('span',{'class':'style-scope ytd-grid-video-renderer'})[1].text
    
    start_url = url_list[i] # 
    browser.get(start_url) 
    time.sleep(1)
    
    # 댓글 정렬
    body = browser.find_element_by_tag_name('body')
    num_of_pagedowns = 1
    while num_of_pagedowns:
        body.send_keys(Keys.PAGE_DOWN)
        time.sleep(1.5) #스크롤 속도 지정 
        num_of_pagedowns -= 1

    time.sleep(1)
    browser.find_element_by_xpath('//*[@class="dropdown-trigger style-scope yt-dropdown-menu"]').click()
    time.sleep(1) 
    browser.find_element_by_xpath('//*[@id="menu"]/a[2]/paper-item').click()   
    
    # 페이지 스크롤
    time.sleep(1) # 브라우저 로딩시간기다려야함
    num_of_pagedowns = 1 #page_down은 댓글이 보일 정도만
    while num_of_pagedowns:
        body.send_keys(Keys.PAGE_DOWN)
        time.sleep(1.5) #스크롤 속도 지정 
        num_of_pagedowns -= 1
        
    time.sleep(1)
    #여기에 time.sleep를 집어 넣는 방법을 고안
    html0 = browser.page_source
    html = BeautifulSoup(html0,'html.parser')
    
    start_date = html.find('div',{'id':'date','class':'style-scope ytd-video-primary-info-renderer'}).text
    comment_num = html.find('h2',{'id':'count'}).find('yt-formatted-string').text
    
    time.sleep(1)        
    #좋아요수
    likes_num = html.find('yt-formatted-string',{'id':'text','class':'style-scope ytd-toggle-button-renderer style-text','aria-label':re.compile('좋아요')}).text+'개'

    #싫어요수
    unlikes_num = html.find('yt-formatted-string',{'id':'text','class':'style-scope ytd-toggle-button-renderer style-text','aria-label':re.compile('싫어요')}).text+'개'

    #댓글 내용
    comment_list = html.find_all('yt-formatted-string',{'id':'content-text'})
    comment_list2 = []
    time.sleep(1)
    for j in range(len(comment_list)) : 
        comment_list2.append(comment_list[j].text)
            
    time.sleep(1)
    insert_data = pd.DataFrame({'name':[name],
                     'thumbnail':[thum],
                     'view':[view],
                     'previous_time':[previous],
                     'video_url':[url],
                     'start_date':[start_date],
                     'comment_num':[comment_num],
                     'likes_num':[likes_num],
                     'unlikes_num':[unlikes_num],
                     'comment_list':[comment_list2]
                     })  
    df = df.append(insert_data)
    
df.index = range(len(df))
df.to_excel('crawling.xlsx', sheet_name='sheet1')

마치며

셀레니움을 활용하여 다양한 크롤링을 할 수 있을 것으로 보인다. 특히 오픈 API와 결합하여 크롤링을 실습해보면 좋을 것 같다.

출처

*Reference : https://shinminyong.tistory.com/2?category=835486

 

유튜브 크롤링

안녕하세요. 업무를 하다가 문득 떠오른 아이디어가 있어서 유튜브 크롤링을 하게 되었습니다. 유튜버들은 유튜브만의 분석 솔루션이 따로 있다고 알고 있는데 "과연, 그것이 얼마나 도움을 줄

shinminyong.tistory.com

'study' 카테고리의 다른 글

지도학습 : 결정트리의 앙상블  (0) 2020.04.15
리그 오브 레전드 승패 예측  (0) 2020.04.13
Youtube 댓글 크롤링  (0) 2020.04.05
지도학습 : 나이브베이즈  (0) 2020.03.30
지도학습 : 선형 모델  (0) 2020.03.29
지도학습 : KNN 최근접 이웃 알고리즘  (0) 2020.03.28

댓글0