관리 메뉴

KoreanFoodie's Study

파이썬 크롤러(유투브 음악 다운로드) 만들기 본문

Tutorials/Python

파이썬 크롤러(유투브 음악 다운로드) 만들기

hashnut 2019. 4. 23. 15:33

파이썬으로 만든 간단한 크롤러

참고 자료 : 웹 크롤러 만들기, Implicit vs. Explict wait 비교하기


 

유투브에서 음악 다운로드하는 작업 자동화 하기

친구가 유투브를 통해 음악을 변환해서 다운로드 받는 것을 보고, 이를 간편하게 해주고자 파이썬 selenium module, chromedriver을 이용해 실행키(Win+R)를 통해 쉽게 음악을 다운로드하는 코드를 작성해 보았습니다. 아, 참고로 mp3juices.cc 라는 사이트로부터 음악을 변환해서 다운을 했는데, 여기가 제일 깔끔한 것 같아요(제 기준)


Prerequsite :

  • Python3 (Latest version is recommemded)

  • Installing 3rd party modules (pyperclip, selenium - using "pip")

  • Add path of mp3.py in System variables(한국말로는 환경 변수) (add github repository directory to your System variable! Reference here)

  • Modify .bat file (Change path to your local directory where .py file lives)


How it works?

2개의 실행 버전이 있습니다. (앞의 버전을 추천)

코드 다운로드는 깃헙을 참고하시면 됩니다.

( + 게시글 맨 뒤에 소스코드를 첨부하였습니다)

 

'실행(Win+R)' 키를 눌러서 바로 다운받기

원하는 검색어나 유투브 링크를 복사하고 '실행(Win+R)' 창에 'mp3와 검색어나 링크'를 누르고 엔터를 치면 됩니다.

3

 

4

(예시 1: 'mp3 https://www.youtube.com/watch?v=aMcjxSThD54&t=1097s')
(예시 2: 'mp3 i want this song')

여러 파일을 다운 받고 싶을 때는 콤마(,)나 슬래시(/)를 통해 구분하면 됩니다.
(예시 3: 'mp3 some love song, some love song2 / some love song3')

파일 다운로드당 최대 1분의 시간이 할당되어 순차적으로 다운로드가 진행됩니다.

크롬 브라우저가 열리며 자동으로 다운로드가 시작하고, 후에 다운이 끝나면 30초 정도 후에 크롬이 자동 종료 됩니다.

(가끔 에러가 뜰 때는 조금 빠르지만 에러가 가끔 나는 버전을 사용해 보세요. mp3 대신 mp3crude를 치면 됩니다!)

 

커맨드 창으로 다운받기

'실행(Win+R)'창에 mp3window를 누르면 cmd 창에서 음악 파일을 다운 받을 수 있는 창이 나옵니다.

1

위의 커맨드 라인에서 원하는 음악에 해당하는 검색어를 입력하면 다운로드가 진행되고, 다운로드가 끝나면 다시 원하는 검색어를 입력합니다.

'quit'를 누르면 프로그램이 종료됩니다.

커맨드 창은 소요시간이 더 크므로, '실행(Win+R)'키로 바로 다운받는 것을 추천합니다.


소스코드 :

실행(Win+R)로 실행하려면 환경변수 설정과 .bat 파일을 생성해야 합니다! (깃헙에 업로드 되어 있음)

#! python3
# test.py - Launches a map in the browser using an address from the
# Windows execute(Win+R)  or command line. (https://mp3juices.cc)

import os, sys, pyperclip

from time import sleep
import re

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC


def downFunc(keyword):

     # Find searchbar and type keyword
     songElem = driver.find_element_by_id('query')
     songElem.send_keys(keyword)

     # Find and push search button
     searchElem = driver.find_element_by_id('button')
     searchElem.click()

     downElem = WebDriverWait(driver, 12) \
                .until(EC.presence_of_element_located((By.CSS_SELECTOR, '.download')))
     sleep(5)
     downElem.click()

     down2Elem = WebDriverWait(driver, 18) \
                .until(EC.presence_of_element_located((By.CSS_SELECTOR, 'a.url')))
     sleep(5)
     down2Elem.click()

     # Clear serchbar for next song
     songElem.clear()

     sleep(20)



# mp3 downloading website
mp3Link = 'https://mp3juices.cc'

driver = webdriver.Chrome()
driver.get(mp3Link)

# Make user Input and store in the list
keywordList = []

# Enter the song info, seperated by slash or comma
userInput = ' '.join(sys.argv[1:])

keywordRegex = re.compile(r'[^/,\r\n]+')
keywordList = keywordRegex.findall(userInput)

while (len(keywordList) > 0):
          downFunc(keywordList[0])
          del keywordList[0]

sleep(30)
driver.quit()
sys.exit()

 


해결해야 할 이슈 :

Issue 1 :

코드에 Headless 옵션을 주어 실행하려고 하면 다음과 같은 에러가 난다.

[0914/115010.508:ERROR:gpu_process_transport_factory.cc(1016)] Lost UI shared context.

DevTools listening on ws://127.0.0.1:52163/devtools/browser/c66a9adf-ac44-41df-b708-95e9c9f68a57

KLIB_SelfTest return : KLR_OK
[0914/115020.497:INFO:CONSOLE(2)] "Service Worker is supported", source: https://defpush.com/ntfc.php?p=1524741 (2)
[0914/115020.499:INFO:CONSOLE(2)] "service worker path:", source: https://defpush.com/ntfc.php?p=1524741 (2)
[0914/115022.009:INFO:CONSOLE(2)] "Service Worker is ready :^)", source: https://defpush.com/ntfc.php?p=1524741 (2)
[0914/115022.016:INFO:CONSOLE(2)] "Request permission status ", source: https://defpush.com/ntfc.php?p=1524741 (2)
[0914/115022.609:INFO:CONSOLE(2)] "registartion done, status:", source: https://defpush.com/ntfc.php?p=1524741 (2)
[0914/115022.662:INFO:CONSOLE(2)] "send: subscriptiondone", source: https://defpush.com/ntfc.php?p=1524741 (2)
[0914/115022.663:INFO:CONSOLE(2)] "service worker was checked for update", source: https://defpush.com/ntfc.php?p=1524741 (2)
[0914/115022.664:INFO:CONSOLE(2)] "send: subscriptiondone", source: https://defpush.com/ntfc.php?p=1524741 (2)
[0914/115028.245:INFO:CONSOLE(2)] "Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/.", source: https://www.mp3juices.cc/js/jquery-3.3.1.min.js (2)
[0914/115029.818:ERROR:in_progress_cache_impl.cc(191)] Cache is not initialized, cannot RetrieveEntry.
[0914/115029.819:ERROR:in_progress_cache_impl.cc(175)] Cache is not initialized, cannot AddOrReplaceEntry.
[0914/115029.820:ERROR:in_progress_cache_impl.cc(191)] Cache is not initialized, cannot RetrieveEntry.

추측 1. 웹 사이트에서 Headless 옵션을 탐지했을 가능성이 있다. (같은 옵션을 주어도 정상적으로 click()이 작동하는 경우도 있음)

추측 2. 동적 웹사이트라서 DOM을 전부 불러오기 전에 클릭했을 가능성이 있다. -> 그런데 implicit wait, explicit wait을 주어도 그에 상관없이 'Cache is not initialiezed...' 에러가 발생한다. time.sleep()으로 간단하게 로딩 시간을 부여했지만.. 여전히 Headless 작동이 안되는 이유는 오리무중

0 Comments
댓글쓰기 폼