언젠가부터인지는 모르겠는데 유튜브 뮤직에서 좋아요 표시를 한 음악에 유튜브에서 좋아요 누른 동영상까지 포함되게 되었어요. (원래 안 그랬는데..)
제가 좋아요 누른 "음악"만 플리에 담고 싶은데 갑자기 침착맨 형님의 수다를 듣게 되더라구요 😂😂
일단 좋아요 누른 동영상을 전부 삭제하자 라는 생각으로
일괄 삭제 기능을 찾아봤지만 없더라구요.
어쩔 수 없이 직접 하나씩 삭제를 하려고 봤더니 좋아요 표시한 동영상 갯수 거의 1000개!?
😇 이건 뭐 수작업으로는 할 수 양이더라구요. 그래서 개발자 도구를 키고 DOM을 잡아가기 시작했습니다.
👆 작업 메뉴 버튼을 선택해보니 aria-label이 "작업 메뉴"
인 버튼들을 가져오면 될 것 같아요.
👆 다만, 다른 영역에서의 버튼과 겹칠 수도 있으니 id가 "contents"인 영역
안에서만으로 한정하겠습니다.
const buttons = document
.querySelector("#contents")
.querySelectorAll('[aria-label="작업 메뉴"]');
👆 자~ 잘 가져와졌죠?
👆 모달은 하나의 모달 코드를 공유하고 있었고 이 부분은 다음($0)과 같이 나왔습니다. 제가 원하는 버튼($1)은 "좋아요 표시한 동영상에서 삭제"
죠? 부모의 마지막 요소에 존재하기에 저는 간단하게 lastElementChild를 사용하여 삭제 버튼을 가져왔습니다.
document.querySelector("tp-yt-paper-listbox#items").lastElementChild
const buttons = document
.querySelector("#contents")
.querySelectorAll('[aria-label="작업 메뉴"]');
for (const [_, button] of buttons.entries()) {
button.click();
document
.querySelector("tp-yt-paper-listbox#items")
.lastElementChild.click();
}
🥵 어라~ 아까는 분명 존재했던 DOM이 null이라서 클릭을 할 수가 없다고 뜨는군요?
이는 높은 확률로
작업 메뉴 버튼
을 클릭하고 모달이 떠서 DOM에 반영되기 전에 javascript 코드가 먼저 실행되는 문제일 것 같네요!
const buttons = document
.querySelector("#contents")
.querySelectorAll('[aria-label="작업 메뉴"]');
for (const [i, button] of buttons.entries()) {
setTimeout(() => {
button.click();
setTimeout(() => {
document
.querySelector("tp-yt-paper-listbox#items")
.lastElementChild.click();
}, 30);
}, i * 60);
}
잘 되네요 👍👍👍
프론트 개발하면서 개발자도구는 정말 뗄래야 뗄 수 없는 관계입니다. 하지만 개발자 도구는 딱 거기까지만 활용하고 그 이상을 활용하지 않고 있었어요.
이번에 단순히 유튜브에서 좋아요를 눌렀던 동영상 목록들을 삭제하기 위한 아주 단촐한 동기로 시작하게 되었습니다.
코드도 그만큼 굉장히 단순했어요. 하지만 직접 해보니 생각보다 개발자도구는 강력할 수 있겠다는 생각을 하게 되었습니다.
개발자도구 이 친구.. 더 알아 가봐야겠어요 ㅎㅎ 👉 크롬 익스텐션 개발도 어렵지 않겠는걸?