-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfetch_channel_thumbnails.py
More file actions
121 lines (95 loc) · 3.72 KB
/
fetch_channel_thumbnails.py
File metadata and controls
121 lines (95 loc) · 3.72 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
"""
fetch_channel_thumbnails.py
각 uploader의 샘플 영상 URL → video_id → channel_id → 채널 썸네일 URL 추출
결과를 src/channelData.js 로 저장
"""
import os
import re
import json
from googleapiclient.discovery import build
from dotenv import load_dotenv
load_dotenv()
API_KEY = os.getenv("YOUTUBE_API_KEY")
MENU_DATA_PATH = "src/menuData_kr.js"
OUTPUT_PATH = "src/channelData.js"
def extract_video_id(url):
m = re.search(r"(?:youtu\.be/|v=)([\w-]{11})", url)
return m.group(1) if m else None
def parse_menu_data():
"""menuData_kr.js에서 uploader별 첫 번째 video_id 추출"""
with open(MENU_DATA_PATH, encoding="utf-8") as f:
content = f.read()
# 중괄호 단위로 각 레시피 블록 분리
blocks = re.split(r'\},\s*\{', content)
uploader_video = {}
for block in blocks:
url_m = re.search(r'"url":\s*"([^"]+)"', block)
upl_m = re.search(r'"uploader":\s*"([^"]+)"', block)
if not url_m or not upl_m:
continue
uploader = upl_m.group(1)
url = url_m.group(1)
if uploader and uploader not in uploader_video:
vid = extract_video_id(url)
if vid:
uploader_video[uploader] = vid
return uploader_video
def fetch_thumbnails(uploader_video):
youtube = build("youtube", "v3", developerKey=API_KEY)
result = {}
video_ids = list(uploader_video.values())
# YouTube API는 한 번에 최대 50개
for i in range(0, len(video_ids), 50):
batch = video_ids[i:i+50]
resp = youtube.videos().list(part="snippet", id=",".join(batch)).execute()
# video_id → channel_id 매핑
vid_to_channel = {}
channel_ids = []
for item in resp.get("items", []):
cid = item["snippet"]["channelId"]
vid_to_channel[item["id"]] = cid
channel_ids.append(cid)
# channel_id → 썸네일 URL
ch_resp = youtube.channels().list(
part="snippet",
id=",".join(set(channel_ids))
).execute()
channel_thumbs = {}
for item in ch_resp.get("items", []):
cid = item["id"]
thumb = (
item["snippet"]["thumbnails"].get("medium", {}).get("url")
or item["snippet"]["thumbnails"].get("default", {}).get("url")
)
channel_thumbs[cid] = thumb
# uploader → 썸네일 연결
for uploader, vid in uploader_video.items():
if vid in vid_to_channel:
cid = vid_to_channel[vid]
if cid in channel_thumbs:
result[uploader] = channel_thumbs[cid]
return result
def write_channel_data(profiles):
lines = ["// Auto-generated by fetch_channel_thumbnails.py",
"// uploader 이름 → YouTube 채널 프로필 이미지 URL",
"",
"const channelProfiles = {"]
for uploader, url in sorted(profiles.items()):
escaped = uploader.replace('"', '\\"')
lines.append(f' "{escaped}": "{url}",')
lines.append("};")
lines.append("")
lines.append("export default channelProfiles;")
with open(OUTPUT_PATH, "w", encoding="utf-8") as f:
f.write("\n".join(lines))
print(f"✅ {len(profiles)}개 채널 프로필 저장 → {OUTPUT_PATH}")
for k, v in profiles.items():
print(f" {k}: {v}")
if __name__ == "__main__":
print("📋 menuData_kr.js 파싱 중...")
uploader_video = parse_menu_data()
print(f" 발견된 uploader {len(uploader_video)}명: {list(uploader_video.keys())}")
print("\n🌐 YouTube API 호출 중...")
profiles = fetch_thumbnails(uploader_video)
print("\n💾 channelData.js 작성 중...")
write_channel_data(profiles)