먼저 아작스 Cross-Origin Same Origin 정책을 극복하기 위해서
울 서버에서 바로 외부 URL을 요청하고 내용을 돌려줄 수 있는(우회) 라이브러리를 설치
여기선 아파치 httpclient5를 설치(fluent는 더 짧고 편하게 쓸 수 있도록 해주는 라이브러리)
<!-- 서버단에서 외부 서버URL 요청 -->
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
<version>5.2.1</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5-fluent</artifactId>
<version>5.2.1</version>
</dependency>
포인또는 아래 첫번째 유투브 URL을 이용하여 검색내용에서 관련 영상 코드를 수집하고
해당코드를 두번째 URL을 이용하여 해당 영상코드의 제목을 찾아오는 것
https://www.youtube.com/results?search_query=검색어
https://www.youtube.com/watch?v=영상코드(11자리)
컨트롤러 맹글기
package com.jaehan.dumb.controller;
import java.io.IOException;
import java.net.URLEncoder;
import javax.servlet.http.HttpServletResponse;
import org.apache.hc.client5.http.fluent.Request;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Controller
@RequestMapping("/youtube")
public class YoutubeController {
@GetMapping("/main")
public String youMain() {
return "myYoutube";
}
@GetMapping("/search")
@ResponseBody
public String schYoutube(String schWord) throws Exception {
//log.debug("schWord:" + URLEncoder.encode(schWord, "UTF-8"));
return Request.get("https://www.youtube.com/results?search_query="+URLEncoder.encode(schWord, "UTF-8"))
.execute().returnContent().toString();
}
@GetMapping(value="/schTitle",produces = "text/plain;charset=utf-8")
@ResponseBody
public String schTitle(String schCode, HttpServletResponse res) throws Exception {
//res.setCharacterEncoding("UTF-8");
log.debug("schCode:" + schCode);
return Request.get("https://www.youtube.com/watch?v="+schCode)
.execute().returnContent().toString();
}
}
jsp 맹글기
주석처리된 부분은 검색된 내용을 배열에 담으려 했음.(필요하다면 사용)
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>This is a e-7-e 유투브</title>
<style>
select {
font-size: 1.1em;
}
</style>
</head>
<body>
<h1>이것은 유투브를 긁어서 맹근 E-7-E 유투브 </h1>
<h3>장점은 광고에 거의 노출이 안됨 </h1>
<h3>단점은 영상 메타정보가 부족하여,자동화가 어려움(다음영상재생등)</h1>
<input type=text value="로제" id="schTxt" placeholder="껌색어 써 주삼" onkeydown="f_enter()"><input type=button value="찾깅" onclick="y_sch()"><br>
<div id="list"></div><br><hr>
<iframe width="1280" id="utube" height="720" src="" title="" frameborder="1" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
<script>
const utubeURL ="https://www.youtube.com/embed/"
const jutube = document.querySelector("#utube");
const sTxt = document.querySelector("#schTxt");
const jlist = document.querySelector("#list");
let arrTitle;
let codeArr;
let jsel;
let conEnter = true;
const f_enter = ()=>{
if(conEnter && event.keyCode == 13){
if(sTxt.value.trim()=="" || sTxt.value.length < 2){
alert("당신은 껌색 바봉");
return;
}
y_sch();
sTxt.value="";
conEnter = false;
setTimeout(()=>{ // 엔터를 막 누르는 사람을 막기 위함!
conEnter = true;
sTxt.focus();
},5000)
}
}
const y_tleSch=(p_code)=>{
//console.log("체킁!");
let xhr = new XMLHttpRequest();
xhr.open("get",`/dumb/youtube/schTitle?schCode=\${p_code}`,true);
xhr.onreadystatechange = () => {
if(xhr.readyState == 4 && xhr.status == 200){
let schContent=xhr.responseText;
let startIndex = schContent.indexOf("<title>");
let endIndex = schContent.indexOf("</title>");
// let startIndex1 = schContent.indexOf('<span class="ytp-time-duration">',0);
// console.log(startIndex1);
// console.log("체킁:",schContent.substring(startIndex1,startIndex+50));
let joption = document.createElement("option");
joption.value = p_code;
joption.innerHTML = `\${schContent.substring(startIndex+7,endIndex)}`;
jsel.appendChild(joption);
jlist.appendChild(jsel);
//console.log("체킹....",jutube.src);
if(jutube.src == location.href){
jutube.src = utubeURL + p_code + "?autoplay=1&mute=1";
console.log(jutube.src);
//<span class="ytp-time-duration">1:12:39</span>
setTimeout(()=>{
console.log(jutube.contentDocument.getElementsByClassName("ytp-time-duration"));
},5000);
}
//arrTitle.push(`\${schContent.substring(startIndex+7,endIndex)}`);
/*
if(arrTitle.length == codeArr.length){
console.log(codeArr);
arrTitle.forEach((sTitle)=>{
let h1 = document.createElement("h1");
h1.innerHTML = sTitle;
disp.appendChild(h1);
})
}
*/
}
}
xhr.send();
}
const y_sch = ()=>{
arrTitle = [];
codeArr = [];
jlist.innerHTML = "";
jutube.src = "";
let schWord = encodeURIComponent(sTxt.value);
let xhr = new XMLHttpRequest();
xhr.open("get",`/dumb/youtube/search?schWord=\${schWord}`,true);
xhr.onreadystatechange = () => {
if(xhr.readyState == 4 && xhr.status == 200){
let schContent=xhr.responseText; // unicode -> utf-8?
let sIndex = 250000;
//console.log("시작체킁:",sIndex);
jsel = document.createElement("select");
jsel.onchange = ()=>{
jutube.src = utubeURL + jsel.value + "?autoplay=1&mute=1";
}
while( (startIndex = schContent.indexOf("watch?v=",sIndex)) != -1){
let sCode = schContent.substr(startIndex+8,11);
sIndex = startIndex + 5000;
//console.log("s인덱스:",sIndex)
//console.log("s코드:",sCode);
if( codeArr.indexOf(sCode) == -1){
y_tleSch(sCode); // 찾고 바로 부르면 좋겠지만, 종료 조건이 애매
//codeArr.push(sCode);
}
}
/*
codeArr.forEach((sCode)=>{
y_tleSch(sCode);
});
console.log("최종",codeArr);
*/
}
}
xhr.send();
}
</script>
</body>
</html>
결과(생각보다 어렵지 않아용!)
맘에 걸리면 ,오래두면 맘을 썩게 할거당.
자백해서 덜어내고 잘라내야 한당.
때론 사과가 부담스러울 수 있당. 안당.
삶을 버티려면 후딱 사과하고 자백해야 한당.
착한 척을 하다가 착해져라.
그거시 이기심을 충족시킬 효율적 방법 중 하나당.!
https://www.youtube.com/watch?v=3PuvxiPIJjQ
이클립스 패키지 <-> 폴더 바꾸깅 (0) | 2023.08.29 |
---|---|
외부 파일 맵핑 (0) | 2023.02.24 |
파일 업로드 (0) | 2023.01.02 |
Apache POI (0) | 2022.11.16 |
STS3(Spring Tool Suite) 설치 (0) | 2022.10.20 |