관리 메뉴

솜씨좋은장씨

[Python]Selenium을 사용하여 유튜브 댓글 가져오기 본문

Programming/Python

[Python]Selenium을 사용하여 유튜브 댓글 가져오기

솜씨좋은장씨 2019. 9. 14. 11:26
728x90
반응형

제가 즐겨보는 Youtube B Man채널에서 제 최애 영화인 어벤져스 엔드게임의 영화 명장면을 정리한 어벤져스 엔드게임 명장면 총정리라는 영상의 댓글 가져오기를 해보았습니다.

 

인스타그램 크롤링 코드가 필요하신 분은 아래의 링크를 참고해주세요!

 

[Python] Selenium을 활용하여 인스타그램 크롤링 하기!

이번 글에서는 Python과 Selenium을 활용하여 인스타그램 게시물을 크롤링하는 방법에 대해서 적어보려 합니다. 해당 코드를 활용하여 발생하는 문제는 코드 사용자에게 있음을 알려드립니다. 1. 필

somjang.tistory.com

1. requests와 BeautifulSoup를 활용하여 시도하기

처음에는 requests와 BeautifulSoup를 사용하여 댓글 가져오기를 시도했습니다.

import requests
from bs4 import BeautifulSoup

url = 'https://www.youtube.com/watch?v=xKf0soeFJtY'
req = requests.get(url)
soup = BeautifulSoup(req.text, 'lxml')

youtube_user = soup.select('div#header-author > a > span')

youtube_comments = soup.select('yt-formatted-string#content-text')

위의 코드로 시도했으나 youtube_user와 youtube_comments를 출력해보면

 

아무것도 받아오지 못한 것을 알 수 있습니다.

 

구글 크롬의 개발자도구를 활용하여 이유를 확인할 수 있었습니다.

 

개발자 도구로 동영상 페이지에서 스크롤 전과 후의 html코드를 확인해보면

 

스크롤 전

스크롤 후

스크롤 전과 후를 보면 스크롤 전에는 별다른 데이터를 가지고 있지않지만 스크롤 후에 동적으로 데이터 값을 가져오는 모습을 보이고 있는 것을 볼 수 있었습니다.

 

이런 경우 우리가 사용할 수 있는 라이브러리는 Selenium입니다.

 

설치는 아래의 링크를 참고하기 바랍니다.

 

[Windows]Windows10에 Selenium설치하기

1. 구글 크롬 최신으로 업데이트하기 먼저 크롬의 맨 우측 상단의 세 개의 점을 클릭하여 크롬의 설정페이지로 들어갑니다. 왼쪽 메뉴에서 Chrome 정보를 클릭하여 업데이트를 실시합니다. 다시시작을 클릭하여..

somjang.tistory.com

 

 

2. Selenium활용하여 다시 시도해보기

from selenium import webdriver as wd
from bs4 import BeautifulSoup
import time

driver = wd.Chrome(executable_path="chromedriver.exe")
url = 'https://www.youtube.com/watch?v=xKf0soeFJtY'
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:
        break
    last_page_height = new_page_height
    

html_source = driver.page_source

driver.close()

soup = BeautifulSoup(html_source, 'lxml')

이번엔 Selenium을 활용하여 시도해 보았습니다.

 

앞 서 스크롤을 해주어야 데이터가 로딩되는 것을 보았기에

 

아래의 코드를 사용하여 현재 페이지의 가장 아래까지 스크롤하였습니다.

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:
        break
    last_page_height = new_page_height

코드를 실행하면

자동으로 스크롤 하여 최대한 아래로 내려갑니다.

 

끝까지 내려가도록 코드를 작성하긴 하였지만 네트워크 상태, 개발 환경의 성능에 따라 다를 수 있습니다.

 

아직 위의 코드에는 단순히 time함수로 3초에 한번씩 스크롤을 내리라고만 하고 있기때문에 3초이내에 새로운 댓글이 로딩되지않는다면 끝까지 내려가지 않고 중간에 멈추고 종료되는 것 같습니다.

html_source = driver.page_source

최대한 아래로 내려갔다면 위의 코드로 페이지의 데이터를 받아옵니다.

soup = BeautifulSoup(html_source, 'lxml')

그럼 받아온 데이터를 BeautifulSoup로 파싱해줍니다.

 

이 코드에서는 lxml parser를 사용했습니다.

 

자 그럼 받아온 코드에서 댓글을 단 유저 ID, 댓글을 받아와 보겠습니다.

 

크롬 개발자도구를 활용하여 태그의 id또는 class값을 확인합니다.

댓글 단 유저이름은 id값이 headear-author인 div태그 안에있는 a태그안에 들어있는 것을 확인할 수 있습니다.

댓글은 id값이 content-text인 yt-formatted-string태그 안에 값이 들어있는 것을 확인할 수 있습니다.

 

BeautifulSoup의 select함수를 사용하여 코드로 구현하면 아래와 같습니다.

youtube_user_IDs = soup.select('div#header-author > a > span')

youtube_comments = soup.select('yt-formatted-string#content-text')
str_youtube_userIDs = []
str_youtube_comments = []

for i in range(len(youtube_user_IDs)):
    str_tmp = str(youtube_user_IDs[i].text)
#     print(str_tmp)
    str_tmp = str_tmp.replace('\n', '')
    str_tmp = str_tmp.replace('\t', '')
    str_tmp = str_tmp.replace('                ','')
    str_youtube_userIDs.append(str_tmp)
    
    str_tmp = str(youtube_comments[i].text) 
    str_tmp = str_tmp.replace('\n', '')
    str_tmp = str_tmp.replace('\t', '')
    str_tmp = str_tmp.replace('               ', '')
   
    str_youtube_comments.append(str_tmp)

받아온 데이터에 들어있는 의미없는 값들을 처리해줍니다.

for i in range(len(str_youtube_userIDs)):
    print(str_youtube_userIDs[i], str_youtube_comments[i])

위와 같이 처리된 데이터를 출력하여 제대로 처리가 되었는지 확인해봅니다.

 

잘 처리는 되었으나 가독성의 면에서 떨어지는 것을 볼 수 있습니다.

 

3. 가져온 댓글 Pandas의 DataFrame을 활용하여 가독성 높이기

import pandas as pd

pd_data = {"ID":str_youtube_userIDs, "Comment":str_youtube_comments}

youtube_pd = pd.DataFrame(pd_data)

먼저 str_youtube_userIDs와 str_youtube_comments의 데이터를 가지는 pd_data라는 딕셔너리를 만들어주고

 

pd.DataFrame(pd_data)하여 DataFrame을 만들어줍니다.

 

만들어진 DataFrame을 확인해보면

 

조금은 보기 편해진 것을 볼 수 있습니다.

 

4. 아직 의문으로 남은점

댓글은 2417개로 표시되지만

Selenium을 실행하여 데이터를 가져오면 실행할때마다

40~300개 사이의 계속 다른 개수의 데이터를 받아오는 점이 의문입니다.

 

추측 1

개발 환경의 컴퓨터 성능이나 네트워크 성능에의해 3초 이내에 로딩이 되지 않아 Webdriver가 종료된다.

 

추측 2

 

Webdriver에서 데이터를 받아올 때 까지 기다려주는 함수를 사용하지않아 Webdriver가 다 받아오기 전에 종료된다.

 

의문점은 더 공부해서 해결 후 포스팅 해보려합니다~

 

5. 질문에 대한 답변들

Q. 여러 URL 속의 댓글을 크롤링하고 싶어요!

A. 아래와 같이 크롤링하고 싶은 url들을 리스트에 담은 후 반복문을 통해 실행하면됩니다.

from selenium import webdriver as wd
from bs4 import BeautifulSoup
import time

urls = ['https://www.youtube.com/watch?v=xKf0soeFJtY', 'https://www.youtube.com/watch?v=_SgZ0VqJd3w', 'https://www.youtube.com/watch?v=m17R1LMhp3Q&t=452s', 'https://www.youtube.com/watch?v=C_DQTLCERnM', 'https://www.youtube.com/watch?v=7hD2L89cjWc']

html_sources = []

for i in range(0, 5):
    driver = wd.Chrome(executable_path="./chromedriver")
    driver.get(urls[i])

    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:
            break
        last_page_height = new_page_height


    html_source = driver.page_source
    html_sources.append(html_source)
    print("OK")

    driver.quit()

 

 

여러 질문 들에 대한 답변을 반영하여 코드를 수정하여 아래의 GitHub에 올려두었습니다.

추후 명령어로 사용이 가능하도록 패키지화 시켜볼 예정입니다.

잘 사용하셨다면 Star한번씩 눌러주세요~

 

SOMJANG/Youtube_Comment_Crawler

유튜브 댓글 크롤러 ( Python, BeautifulSoup, Selenium ). Contribute to SOMJANG/Youtube_Comment_Crawler development by creating an account on GitHub.

github.com

읽어주셔서 감사합니다.

Comments