From 56d5752095b7da09ebaa764857072669a971cbe6 Mon Sep 17 00:00:00 2001 From: joungmin Date: Wed, 1 Apr 2026 07:37:48 +0000 Subject: [PATCH] Add YouTube cookie support to Playwright fallback for bot bypass Load cookies.txt (Netscape format) into Playwright browser context before navigating to YouTube, enabling authenticated access to bypass bot detection that blocks transcript retrieval. Co-Authored-By: Claude Opus 4.6 (1M context) --- .gitignore | 1 + .../service/YouTubeTranscriptService.java | 38 +++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/.gitignore b/.gitignore index fd08fbe..4a843e7 100644 --- a/.gitignore +++ b/.gitignore @@ -67,3 +67,4 @@ oracle_data/ # Claude Code # ======================== .claude/ +cookies.txt diff --git a/sundol-backend/src/main/java/com/sundol/service/YouTubeTranscriptService.java b/sundol-backend/src/main/java/com/sundol/service/YouTubeTranscriptService.java index 8bff2d1..e71276b 100644 --- a/sundol-backend/src/main/java/com/sundol/service/YouTubeTranscriptService.java +++ b/sundol-backend/src/main/java/com/sundol/service/YouTubeTranscriptService.java @@ -14,6 +14,9 @@ import org.springframework.stereotype.Service; import java.io.IOException; import java.net.URLDecoder; import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -118,6 +121,10 @@ public class YouTubeTranscriptService { BrowserContext context = browser.newContext(new Browser.NewContextOptions() .setUserAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36") .setLocale("ko-KR")); + + // YouTube 쿠키 로딩 (봇 차단 우회) + loadCookies(context); + Page page = context.newPage(); page.navigate(watchUrl, new Page.NavigateOptions() @@ -218,6 +225,37 @@ public class YouTubeTranscriptService { return sb.toString(); } + private void loadCookies(BrowserContext context) { + Path cookieFile = Path.of(System.getProperty("user.dir"), "cookies.txt"); + if (!Files.exists(cookieFile)) { + log.warn("cookies.txt not found at: {}", cookieFile); + return; + } + + try { + List lines = Files.readAllLines(cookieFile); + List cookies = new ArrayList<>(); + for (String line : lines) { + if (line.startsWith("#") || line.isBlank()) continue; + String[] parts = line.split("\t"); + if (parts.length < 7) continue; + String domain = parts[0]; + if (!domain.contains("youtube") && !domain.contains("google")) continue; + cookies.add(new com.microsoft.playwright.options.Cookie(parts[5], parts[6]) + .setDomain(domain) + .setPath(parts[2]) + .setSecure("TRUE".equalsIgnoreCase(parts[3])) + .setHttpOnly(false)); + } + if (!cookies.isEmpty()) { + context.addCookies(cookies); + log.info("Loaded {} YouTube cookies", cookies.size()); + } + } catch (Exception e) { + log.warn("Failed to load cookies: {}", e.getMessage()); + } + } + private String extractVideoId(String url) { if (url == null || url.isBlank()) return null; try {