안녕하세요. 선의공입니다.
저는 유튜브 스트리밍을 보는 것을 좋아하는데요!
마침 Google MLB에서의 과정 중 하나인 Gemma Sprint 프로젝트를 정하다가
"최근 LLM을 이용해 채팅을 요약하고 분석해서 한눈에 볼 수 있는 서비스를 제공하면 어떨까?"
라는 생각에 해당 주제의 개인 프로젝트를 진행해보았습니다.
또한 2024년 7월에 공개된 따끈따끈한 Opensource 모델인 Gemma2 모델을 사용해보았습니다.
프로젝트 진행 과정을 블로그에 공유하려고 합니다.
프로젝트는 크게 보면
유튜브 YouTube Live Chat 정보 가져오기 -> Gemma2 LLM 모델을 이용한 채팅 요약 -> 사용자에게 보여주기
의 로직으로 진행될 것 같아요.
이 중 YouTube Live Chat 정보 가져오기 과정에 대해 이번 포스팅에서 진행해볼게요!
1. 채팅 데이터 수집 방향성 파악
먼저 제가 필요한 데이터는 YouTube Live Chat 사용자 채팅 데이터입니다.
유튜브에서는 developer를 위한 라이브 채팅 API가 존재합니다!
https://developers.google.com/youtube/v3/live/getting-started
YouTube Live Streaming API 개요 | Google for Developers
YouTube에서 실시간 이벤트를 만들고 업데이트하고 관리합니다.
developers.google.com
하지만, 이 API를 사용하기 위해서는 기준이 있었습니다.
"라이브 채널의 api-key를 알고 있어야 할 것"
그래서 아래의 방법을 생각했습니다.
1. 수집하고 싶은 라이브 채널의 스트리머에게 동의를 구하고 api-key를 얻음.
2. 내가 직접 라이브 스트리밍을 해서 데이터를 수집하기.
1번은 두 분의 제가 좋아하는 유명 스트리머 분들께 프로젝트 설명과 저의 상황을 포함한 내용의 메일을 보냈지만,,,
답장이 오지 않았고...ㅜㅜㅋㅋ
2번을 직접 시도하였습니다. 직접 라이브 스트리밍 하기.
하지만,,, 한번도 해보지 않아서 PC에서는 웹캠 세팅과 스트리밍 프로그램을 연동해야하고,
핸드폰으로 하려니 구독자 50명을 달성해야 하더라구요....
또한, 채팅 데이터도 적은 수의 지인들의 채팅 데이터가 될 것 같고,
General한 데이터가 모일 것 같지 않았습니다.
그래서.. 이런 복잡한 과정의 이유로 Cwawling 라이브러리를 사용하기로 결정했습니다.
2. Python YouTube Crawling 라이브러리 확인
Python으로 채팅 데이터를 Crawling 하기 위해서
pytchat 라이브러리가 필요합니다.
만약 스트리밍 정보를 가져오고 싶다면 pafy , youtube-dl 라이브러리를 사용합니다.
pytchat : 채팅 정보를 가져오기 위한 라이브러리
pafy : 스트리밍 정보를 가져오기 위한 라이브러리
youtube-dl : pyfy에서 유튜브 정보를 사용할 때 필요한 라이브러리
저는 스트리밍 정보도 사용자에게 노출하고 싶어서 pyfy를 사용할 예정입니다.
스트리밍 정보에는 라이브 방송명, 채널명, 스트리밍 시작시간 등이 포함됩니다.
pafy를 사용해서 스트리밍 정보를 가져오기 위해서는 youtube_api_key가 필요합니다.
api-key를 만들어보겠습니다.
3. youtube_api_key 생성
(만약 pytchat만 사용할 예정이시라면 이 과정은 생략하셔도 괜찮습니다!)
3-1. 먼저 Google Cloud Console 페이지로 접속을 합니다.
https://console.cloud.google.com/apis/library?hl=ko&supportedpurview=project
Google Cloud console
Google Cloud 콘솔에서 www.gstatic.com의 자바스크립트 소스를 로드할 수 없습니다. 가능한 원인은 다음과 같습니다. 네트워크 관리자가 www.gstatic.com 또는 IP 주소를 차단합니다.과도한 자동 요청으로
console.cloud.google.com
3-2. YouTube Data API v3 를 찾아 클릭하고
3-3. 사용을 눌러주세요.
3-4. 프로젝트가 없다고 하면 왼쪽 상단의 리스트버튼을 눌러 프로젝트 생성을 해주셔야 합니다.
3-5. 저는 "YOUTUBE-live-chat" 이라는 이름의 프로젝트를 생성해 주었습니다.
3-6. 다시 YouTube Data API v3로 들어가서 사용을 눌러주면
아래와 같이 API 서비스를 관리할 수 있는 페이지가 노출됩니다.
여기서 "사용자 인증 정보"를 눌러줍니다.
3-7. 여기서 API 키를 생성하겠습니다.
상단에 "사용자 인증 정보 만들기"-> "API 키"
3-8. 키가 생성되었습니다. 우측의 해당 API key가 youtube_api_key 입니다.
이제부터 크롤링시에 이 키를 사용합니다.
4. 환경설정
4-1. 이제 환경 설정을 해보겠습니다.
저는 anacoda를 사용해서 가상 환경을 만들겠습니다.
만약 anaconda등 기본 환경 설정이 되어있지 않으신 분은 아래의 포스팅을 참고해주세요.
https://aigaeddo.tistory.com/2
[Tensorflow] 1. Python과 Tensorflow를 이용한 인공지능 개발 세팅하기
안녕하세요. 오늘은 Python와 Tensorflow를 이용한 머신러닝,딥러닝 기초학습을 하기 위한 개발 세팅을 해보았습니다. 이 학습을 하기 위해서 컴퓨터를 세팅해주었습니다. 필요한 것은 아래 4가지입
aigaeddo.tistory.com
터미널에 아래와 같은 명령어를 입력해줍니다.
youtube_chat이라는 가상환경에 python은 3.11로 깔아주었습니다.
conda create -n youtube_chat python=3.11
4-2. activate를 해서 가상환경에 들어가 줍니다.
이제부터 해당 프로젝트에서 이 가상환경을 사용해줄 예정입니다.
conda activate youtube_chat
4-3. 필요한 라이브러리 설치
pytchat, pyfy, youtube-dl 라이브러리를 설치하겠습니다.
pip install pytchat pafy youtube-dl
5. Python Crawling 코딩
먼저 시작하기에 앞서 YouTube 스트리밍 정보를 가져오기 위한 youtube-dl 라이브러리의 자잘한 오류가 있더라구요,
혹시 오류가 발생한다면 아래의 블로그를 참고해서 해결해주세요.
(pytchat만 사용할 거라면 해당 없음..)
[오류 모음]youtube-dl, pytube, youtube.py(NotFoundError, like_count, OSError)
1. youtube-dl 패키지 오류 ModuleNotFoundError: No module named 'youtube_dl' 혹은 ImportError: pafy: youtube-dl not found; you can use the internal backend by setting the environmental variable PAFY_BACKEND to "internal". It is not enabled by default
mvcv.tistory.com
5-1. 설치한 라이브러리를 사용하기 위해 import를 진행합니다.
import pafy.backend_internal
import pafy.backend_youtube_dl
import pytchat
import pafy
추가적으로
pandas: 채팅 데이터를 저장하기 위해 사용할 라이브러리
time: 시간 체크를 위해 사용할 라이브러리
tqdm: crawling 진행 과정을 확인하기 위한 시각화 라이브러리
도 사용할 예정이므로 import 해주었습니다.
import pandas as pd
import time
from tqdm import tqdm
5-2. 일단 Crawler 라는 클래스를 하나 생성해주었습니다.
이제부터 프로젝트에서 Crawling을 담당할 직원입니다.
class Chat_Crawler:
def __init__(self, collect_time, youtube_api_key, video_id):
self.collect_time = collect_time # 댓글 수집 시간 (초)
self.youtube_api_key = youtube_api_key
self.video_id = video_id
self.file_path = f"./data/{video_id}_chat.csv"
#pafy가 참고할 BACKEND 정보 key 설정
os.environ['PAFY_BACKEND'] = 'yt-dlp'
#pafy youtube_api_key 설정
pafy.set_api_key(self.youtube_api_key)
Crawler는 아래의 파라미터를 입력받고 사용합니다.
collect_time | 채팅을 수집할 시간 |
youtube_api_key | 위에서 생성한 youtube api key |
video_id: | 스트리밍 video id (https://www.youtube.com/watch?v=7_HuiArBnrA) 스트리밍 링크에서 굵은 글씨에 해당 |
file_path | crawling한 채팅을 저장할 경로 |
추가로 인스턴스 시에 pafy 설정도 진행해주었습니다.
5-3. Crawling
do_crawling() 메서드가 Crawling을 하는 코드입니다.
댓글 작성자, 댓글 내용, 댓글 작성 기간을 Crawling 해주었습니다.
__create_chat_instance() 메서드를 생성해서 스트리밍 video_id에 해당하는 pytchat 인스턴스를 만들어주었고
채팅 파일을 휘발성으로 사용하기로 했으므로,
__remove_existing_file() 라는 private한 메서드를 생성해주었습니다.
def __create_chat_instance(self):
return pytchat.create(video_id=self.video_id, interruptable=False)
def __remove_existing_file(self):
if os.path.exists(self.file_path):
os.remove(self.file_path)
print(f"기존 파일 {self.file_path} 삭제 완료.")
else:
print(f"삭제할 파일이 없습니다: {self.file_path}")
def do_crawling(self):
# 기존 파일이 있을 경우 삭제
self.__remove_existing_file()
# CSV 파일 새로 생성
empty_df = pd.DataFrame(columns=['댓글 작성자', '댓글 내용', '댓글 작성 시간'])
empty_df.to_csv(self.file_path, index=False, encoding='utf-8-sig')
# 채팅 인스턴스 생성
chat = self.__create_chat_instance()
# 시작 시간 기록
start_time = time.time()
# tqdm - croling 진행 프로그래스바로 시각화
with tqdm(total=self.collect_time, desc="crawling 진행 중", unit="초", bar_format="{l_bar}{bar}| {remaining}") as pbar:
while chat.is_alive():
try:
current_time = time.time()
elapsed_time = current_time - start_time # 경과 시간 계산
# 수집 시간이 지나면 루프 종료
if elapsed_time >= self.collect_time:
break
data = chat.get()
items = data.items
for c in items:
df = {
'댓글 작성자': [c.author.name],
'댓글 내용': [c.message],
'댓글 작성 시간': [c.datetime]
}
result = pd.DataFrame(df)
result.to_csv(self.file_path, mode='a', header=False, index=False, encoding='utf-8-sig')
# 경과 시간만큼 프로그래스바 갱신
pbar.update(current_time - start_time - pbar.n)
except KeyboardInterrupt:
chat.terminate()
print("crawling 오류")
break
except Exception as e:
chat.terminate()
print("crawling 오류")
print(f"Error while processing chat data: {e}")
break
print("-crawling 완료-")
또한 추가적으로 video 정보가 필요해서 추가로 get_video() 메서드를 만들어주었습니다.
def get_video(self):
video = pafy.new(self.video_id)
return video
아래는 Crawler 전체 코드입니다.
import pafy.backend_internal
import pafy.backend_youtube_dl
import pytchat
import pafy
import pandas as pd
import time
import os
from tqdm import tqdm
class Chat_Crawler:
def __init__(self, collect_time, youtube_api_key, video_id):
self.collect_time = collect_time # 댓글 수집 시간 (초)
self.youtube_api_key = youtube_api_key
self.video_id = video_id
self.file_path = f"./data/{video_id}_chat.csv"
os.environ['PAFY_BACKEND'] = 'yt-dlp'
pafy.set_api_key(self.youtube_api_key)
def get_video(self):
video = pafy.new(self.video_id)
return video
def __create_chat_instance(self):
return pytchat.create(video_id=self.video_id, interruptable=False)
def __remove_existing_file(self):
if os.path.exists(self.file_path):
os.remove(self.file_path)
print(f"기존 파일 {self.file_path} 삭제 완료.")
else:
print(f"삭제할 파일이 없습니다: {self.file_path}")
def do_crawling(self):
# 기존 파일이 있을 경우 삭제
self.__remove_existing_file()
# CSV 파일 새로 생성
empty_df = pd.DataFrame(columns=['댓글 작성자', '댓글 내용', '댓글 작성 시간'])
empty_df.to_csv(self.file_path, index=False, encoding='utf-8-sig')
# 채팅 인스턴스 생성
chat = self.__create_chat_instance()
# 시작 시간 기록
start_time = time.time()
# tqdm - croling 진행 프로그래스바로 시각화
with tqdm(total=self.collect_time, desc="crawling 진행 중", unit="초", bar_format="{l_bar}{bar}| {remaining}") as pbar:
while chat.is_alive():
try:
current_time = time.time()
elapsed_time = current_time - start_time # 경과 시간 계산
# 수집 시간이 지나면 루프 종료
if elapsed_time >= self.collect_time:
break
data = chat.get()
items = data.items
for c in items:
df = {
'댓글 작성자': [c.author.name],
'댓글 내용': [c.message],
'댓글 작성 시간': [c.datetime]
}
result = pd.DataFrame(df)
result.to_csv(self.file_path, mode='a', header=False, index=False, encoding='utf-8-sig')
# 경과 시간만큼 프로그래스바 갱신
pbar.update(current_time - start_time - pbar.n)
except KeyboardInterrupt:
chat.terminate()
print("crawling 오류")
break
except Exception as e:
chat.terminate()
print("crawling 오류")
print(f"Error while processing chat data: {e}")
break
print("-crawling 완료-")
5. 테스트
코드 기능 테스트를 진행했습니다.
import os
#Test
if __name__ == "__main__":
from dotenv import load_dotenv
load_dotenv()
api_key = os.getenv('YOUTUBE_API_KEY')
croling_instance = Chat_Crawler(collect_time=10, youtube_api_key=api_key, video_id="lDcWeklf6DI")
croling_instance.do_crawling()
os.getenv???<<라는 코드가 있는데요.
저는 api key를 .env 환경변수로 관리했습니다.
방법은 아래의 블로그를 따라하시면 됩니다.
https://velog.io/@ggydo59/python-%ED%99%98%EA%B2%BD%EB%B3%80%EC%88%98-%EC%84%B8%ED%8C%85.env
[python] 환경변수 세팅(.env)
💡 <span style='color:띄어쓰기 없이 입력해야 합니다.Git 업로드시 환경변수 파일을 업로드하면 안되므로, .gitignore에 .env파일을 추가해 줍니다.python에서 .env 설정파일사용하기python-dotenv project descri
velog.io
실행 결과 Crawling이 진행되는 것을 확인할 수 있었습니다.
채팅도 잘 들어오네요!
다음 포스팅에서는
Crawling한 채팅 데이터로 Gemma모델을 사용해서 채팅 요약과 분석을 진행 해보겠습니다.
보완점이 있다면 지적 부탁드리겠습니다!
#GemmaSprint
'인공지능 개발하기 > AI Projects' 카테고리의 다른 글
[Gemma2 모델을 이용한 유튜브 실시간 채팅 요약 프로젝트] 3) Flask를 이용한 Web Service 제공 (1) | 2024.10.02 |
---|---|
[Gemma2 모델을 이용한 유튜브 실시간 채팅 요약 프로젝트] 2) Chat Summarization with LLM (0) | 2024.10.02 |
[YOLOv5 프로젝트] 특정 사람 얼굴 인식하기(2) (1) | 2024.03.30 |
[YOLOv5 프로젝트] 특정 사람 얼굴 인식하기(1) (3) | 2024.03.29 |