본문 바로가기
프로젝트(홀딩)/유튜브 댓글분석

[댓심]크롤링 프로그램 제작2: 대댓글 크롤링

by 일말고프로젝트 2021. 4. 8.

2021.04.07 - [프로젝트/유튜브 댓글분석] - [댓심]유튜브 댓글 크롤링 프로그램 제작기1

 

우선 대댓글이 달린 원 댓글을 대댓글 데이터에 함께 저장하려 시도했다. FK 개념으로 원 댓글에 고유 번호를 부여한 후 대댓글에 FK를 부여하려 했지만, 대댓글이 달리지 않은 댓글의 경우 크롤링 할 내용이 없기 때문에 NULL 값이 아닌 아예  건너뛰게 된다.

 

정리해보면

 

1. 대댓글이 없는 댓글을 식별할 수 없다 

2. 원 댓글과 인덱스를 맞출 수 없음.

3. 댓글과 대댓글의 관계를 정보화 할 수 없음

 

 

대댓글 크롤링 어렵다..

 


역시 비슷한 문제를 해결하신 분이 계셨다.

 

blog.naver.com/blueqnpfr1/222069530876

 

[PYTHON] 셀레니움(selenium)을 활용한 유튜브 댓글 크롤링

계기오랜만에 포스팅을 한다. 최근에 알게 된 지인으로부터 크롤링 외주 의뢰를 하나 받았는데그걸 하고 나...

blog.naver.com

 

과정은 이렇다.

1. 유튜브 페이지 열기
2. 페이지 스크롤 다운
3. 대댓글 다열기
4. 파싱 - 댓글별 대댓글 파싱

추가해보자면 댓글과 대댓글의 관계만 표시해서 가져오면 끝!

여기서 조금 수정해야 할 건 기존의 댓글 내용, 아이디, 좋아요수를 개별적으로 파싱했던 것을 댓글별로 파싱하는 것으로 수정해야 한다.

comments = soup.select("yt-formatted-string#content-text")
comments = soup.find_all("ytd-comment-thread-renderer", class_ = "style-scope ytd-item-section-renderer")

댓글을 찾고, 그 안에 댓글 내용, ID, 좋아요수 그리고 대댓글까자 불러와야 하기 때문에 더 상위개념을 파싱했다.

 

최종 생각한 테이블을 정리해보면

 

(원 댓글)

인덱스 아이디 내용 좋아요수
1 a ㅇㅇ 123
2 b ㅇㅇㅇ 23
3 c ㅇㅇㅇㅇ 15
4 d ㅇㅇㅇㅇ 746

 

(대댓글)

원댓글 인덱스 아이디 내용 좋아요수
1 xw ㅇㅇ 123

 

이렇게 정리해서 보면 좋을 듯 하다.

 

최종 결과물은 이렇다!

원댓글 DF
대댓글 DF

 

최종 코드

#패키지 불러오기
from selenium import webdriver as wd
from bs4 import BeautifulSoup
import time
import re
import pandas as pd

#기본 설정
driver = wd.Chrome(executable_path="C:/Users/MSI/OneDrive/바탕 화면/youtube/chromedriver.exe")
url = 'https://www.youtube.com/watch?v=yDD4K-XxuDY'
driver.get(url)

#스크롤 내리기
last_page_height = driver.execute_script("return document.documentElement.scrollHeight")

while True: 
    driver.execute_script("window.scrollTo(0, document.documentElement.scrollHeight);")
    time.sleep(3.0)
    new_page_height = driver.execute_script("return document.documentElement.scrollHeight")
    if new_page_height == last_page_height:
        time.sleep(3.0)
        if new_page_height == driver.execute_script("return document.documentElement.scrollHeight"):
            break
    else:
        last_page_height = new_page_height

#대댓글 다열기
rereple = driver.find_elements_by_css_selector("#more-replies")
for re in rereple:
    driver.execute_script("arguments[0].click()", re)       

#파싱
source = driver.page_source
     
soup = BeautifulSoup(source, 'lxml')

#데이터 저장
ids = []
com = []
like = []
N = 1

comments = soup.find_all("ytd-comment-thread-renderer", class_ = "style-scope ytd-item-section-renderer")

re_ids = []
re_coms = []
re_likes = []

#댓글별 ID,내용,좋아요,대댓글 저장
for comment in comments :
    
    #ID 넣기
    ids_temp = str(comment.find("span", class_="style-scope ytd-comment-renderer").text)
    ids_temp = ids_temp.replace('\n', '')
    ids_temp = ids_temp.replace('            ', '')
    ids_temp = ids_temp.replace('              ', '')
    ids_temp = ids_temp.replace('  ', '')
    ids.append(ids_temp)
    
    
    #댓글 내용
    com_temp = str(comment.find("yt-formatted-string", id="content-text").text)
    com_temp = com_temp.replace('\n', '')
    com.append(com_temp)
    
    #좋아요
    likes_temp = str(comment.find("span", id = "vote-count-middle").text)
    likes_temp = likes_temp.replace('\n', '')
    likes_temp = likes_temp.replace('    ', '')
    likes_temp = likes_temp.replace('  ', '')
    like.append(int(likes_temp))
    
    #대댓글
    replies = comment.find_all("ytd-comment-renderer", class_="style-scope ytd-comment-replies-renderer")
    
    for replie in replies:
    
    #ID 넣기
        re_ids_temp = str(replie.find("span", class_="style-scope ytd-comment-renderer").text)
        re_ids_temp = re_ids_temp.replace('\n', '')
        re_ids_temp = re_ids_temp.replace('            ', '')
        re_ids_temp = re_ids_temp.replace('              ', '')
        re_ids_temp = re_ids_temp.replace('  ', '')
        re_id = (N, re_ids_temp)
        re_ids.append(re_id)
    
    
    #댓글 내용
        re_com_temp = str(replie.find("yt-formatted-string", id="content-text").text)
        re_com_temp = re_com_temp.replace('\n', '')
        re_com = (N, re_com_temp)
        re_coms.append(re_com)
    
    #좋아요
        re_likes_temp = str(replie.find("span", id = "vote-count-middle").text)
        re_likes_temp = re_likes_temp.replace('\n', '')
        re_likes_temp = re_likes_temp.replace('    ', '')
        re_likes_temp = re_likes_temp.replace('  ', '')
        re_like = (N, re_likes_temp)
        re_likes.append(re_like)

    N = N+1
    
re_df = pd.DataFrame({"INDEX": list(range(1, len(ids)+1)), "ID": ids, "REPLY" : com, "LIKE" : like})

rere_id = pd.DataFrame(re_ids)
rere_com = pd.DataFrame(re_coms)
rere_like = pd.DataFrame(re_likes)

rere_df = pd.DataFrame({"INDEX" : rere_id[0], "ID": rere_id[1], "REPLY" : rere_com[1], "LIKE" : rere_like[1]})

이젠 분석할 시간

댓글