Skip to content

Commit 7735f6b

Browse files
committed
fix curation crawling api with yotube data api v3
1 parent ef692dc commit 7735f6b

File tree

1 file changed

+83
-25
lines changed

1 file changed

+83
-25
lines changed
Lines changed: 83 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package com.wable.www.WableServer.api.curation.service;
22

3+
import com.fasterxml.jackson.databind.JsonNode;
4+
import com.fasterxml.jackson.databind.ObjectMapper;
35
import com.wable.www.WableServer.api.curation.domain.Curation;
46
import com.wable.www.WableServer.api.curation.dto.request.CurationPostRequestDto;
57
import com.wable.www.WableServer.api.curation.repository.CurationRepository;
@@ -9,51 +11,107 @@
911
import org.jsoup.Jsoup;
1012
import org.jsoup.nodes.Document;
1113
import org.jsoup.nodes.Element;
14+
import org.springframework.beans.factory.annotation.Value;
1215
import org.springframework.stereotype.Service;
1316
import org.springframework.transaction.annotation.Transactional;
17+
import org.springframework.web.client.RestTemplate;
18+
import org.springframework.web.util.UriComponentsBuilder;
1419

1520
@Service
1621
@RequiredArgsConstructor
1722
@Transactional
1823
public class CurationCommandService {
24+
1925
private final CurationRepository curationRepository;
2026

27+
@Value("${youtube.api-key}")
28+
private String youtubeApiKey;
29+
30+
private static final String YOUTUBE_API_URL = "https://www.googleapis.com/youtube/v3/videos";
31+
2132
public void postCuration(CurationPostRequestDto curationPostRequestDto) {
2233
String link = curationPostRequestDto.curationLink();
23-
24-
// 기본값 (메타 태그 없을 경우 대비)
2534
String title = null;
2635
String thumbnail = null;
2736

2837
try {
29-
Document doc = Jsoup.connect(link)
30-
.userAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) " +
31-
"AppleWebKit/537.36 (KHTML, like Gecko) " +
32-
"Chrome/120.0.0.0 Safari/537.36")
33-
.timeout(5000)
34-
.get();
35-
36-
Element ogTitle = doc.selectFirst("meta[property=og:title]");
37-
if (ogTitle != null) {
38-
title = ogTitle.attr("content");
39-
} else if (doc.title() != null) {
40-
title = doc.title();
41-
}
38+
if (isYouTubeLink(link)) {
39+
String videoId = extractVideoId(link);
40+
if (videoId == null) {
41+
throw new BadRequestException("유효하지 않은 유튜브 링크입니다.");
42+
}
43+
44+
String uri = UriComponentsBuilder.fromHttpUrl(YOUTUBE_API_URL)
45+
.queryParam("part", "snippet")
46+
.queryParam("id", videoId)
47+
.queryParam("key", youtubeApiKey)
48+
.toUriString();
49+
50+
RestTemplate restTemplate = new RestTemplate();
51+
String response = restTemplate.getForObject(uri, String.class);
52+
53+
ObjectMapper mapper = new ObjectMapper();
54+
JsonNode root = mapper.readTree(response);
55+
JsonNode items = root.path("items");
56+
57+
if (!items.isArray() || items.size() == 0) {
58+
throw new BadRequestException("유튜브 영상 정보를 찾을 수 없습니다.");
59+
}
60+
61+
JsonNode snippet = items.get(0).path("snippet");
62+
title = snippet.path("title").asText();
63+
thumbnail = snippet.path("thumbnails").path("high").path("url").asText();
64+
65+
} else {
66+
Document doc = Jsoup.connect(link)
67+
.userAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) " +
68+
"AppleWebKit/537.36 (KHTML, like Gecko) " +
69+
"Chrome/120.0.0.0 Safari/537.36")
70+
.timeout(5000)
71+
.get();
4272

43-
Element ogImage = doc.selectFirst("meta[property=og:image]");
44-
if (ogImage != null) {
45-
thumbnail = ogImage.attr("content");
73+
Element ogTitle = doc.selectFirst("meta[property=og:title]");
74+
if (ogTitle != null) {
75+
title = ogTitle.attr("content");
76+
} else if (doc.title() != null) {
77+
title = doc.title();
78+
}
79+
80+
Element ogImage = doc.selectFirst("meta[property=og:image]");
81+
if (ogImage != null) {
82+
thumbnail = ogImage.attr("content");
83+
}
4684
}
85+
86+
// DB 저장
87+
curationRepository.save(
88+
Curation.builder()
89+
.curationLink(link)
90+
.curationTitle(title)
91+
.curationThumbnail(thumbnail)
92+
.build()
93+
);
94+
4795
} catch (Exception e) {
96+
e.printStackTrace();
4897
throw new BadRequestException(ErrorStatus.CRAWLING_ERROR.getMessage());
4998
}
99+
}
100+
101+
private boolean isYouTubeLink(String url) {
102+
return url.contains("youtube.com/watch?v=") || url.contains("youtu.be/");
103+
}
50104

51-
Curation curation = curationRepository.save(
52-
Curation.builder()
53-
.curationLink(link)
54-
.curationTitle(title)
55-
.curationThumbnail(thumbnail)
56-
.build()
57-
);
105+
private String extractVideoId(String url) {
106+
try {
107+
if (url.contains("v=")) {
108+
return url.substring(url.indexOf("v=") + 2).split("&")[0];
109+
} else if (url.contains("youtu.be/")) {
110+
return url.substring(url.indexOf("youtu.be/") + 9).split("\\?")[0];
111+
}
112+
return null;
113+
} catch (Exception e) {
114+
return null;
115+
}
58116
}
59117
}

0 commit comments

Comments
 (0)