멜론 플레이리스트 다운로더 / 다운로드 방법
유투브의 api 변환으로 이제 작동 안함 언제 고칠지는 미정
**이 프로젝트는 순수히 웹 스크래핑 취약점의 교육을 목적으로 제작된 것입니다.**
설치 방법
1. FFmpeg를 설치한다
이 프로젝트를 실행하기 위해서는 음악 파일 변환을 담당하는 FFmpeg를 사용해야 합니다. 다운을 받는 방법은 https://ko.wikihow.com/%EC%9C%88%EB%8F%84%EC%9A%B0%EC%97%90-FFmpeg-%EC%84%A4%EC%B9%98%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95
윈도우에 FFmpeg 설치하는 방법
윈도우 10 컴퓨터에 FFmpeg를 설치하는 방법을 알아보자. FFmpeg는 명령줄 전용 프로그램으로 동영상과 오디오를 다른 형식으로 바꾸고 라이브 오디오와 동영상을 녹음/녹화할 수 있다. FFmpeg 다운로드 사이트를 연다. 컴퓨터의 웹브라우저에서 [https://ffmpeg.zeranoe.com/builds/ https://ffmpeg.zeranoe.com/builds/]로 이동한다.
ko.wikihow.com
여기에 친절하게 설명되있음으로 따라하시면 됩니다
2. exe 파일을 다운받는다
https://drive.google.com/file/d/1hscsm4RLMUy4Db9zEDK08gR3_b_8GXnc/view?usp=sharing
melon playlist downloader.exe
drive.google.com
여기에서 다운받으시면 됩니다.
3. 실행시킨다
실행을 시키려하면 경고가 뜰겁니다. 그냥 무시하시고 실행 시키시면 됩니다. 바이러스 없습니다 제가 제 손으로 만든겁니다. 밑에 소스코드도 있습니다.
4. 사용한다
다운을 받고싶은 폴더경로를 예시에 제시된 형식으로 입력합니다. \가 아니라/ 입니다 C:/ 필요없습니다.
여러분의 멜론 플레이리스트 링크를 넣으세요. (멜론 플레이리스트 링크를 어떻게 알아내는 건지 궁금하시다면 밑에 설명을 보시면 됩니다.
플레이리스트 링크를 구할수 있는 방법은
https://memory112.tistory.com/657
멜론 플레이리스트 공유 방법 (카카오톡)
멜론으로 음악 많이들 들으시죠? 내가 듣고 있는 '플레이리스트'를 다른 사람에게 공유하는 방법이 있다는 것을 알고 계시나요?? 내가 하나하나 쌓아둔 노래들이 담긴 플레이리스트를 지인 또는 친구에게 공유할..
memory112.tistory.com
다음 설명을 따라가서 카카오톡 공유가 아닌 추가 공유방법 선택, 이메일로 공유하기를 누르시면 링크를 얻을 수 있습니다.
링크는 다음과 같은 형식입니다 http://ktto.to/*******
예시 링크 :
이 다운로더의 장점들
1. 몇백개의 곡을 자동으로 무료로 다운받을 수 있다.
2. 곡의 엘범 아트, 엘범이름, 가수 이름등의 정보를 음악 파일에 저장해준다.
소스코드
이 프로젝트는 last.fm API, Beutiful Soup, pytube를 통해서 만들어졌습니다
필요한 모듈은 다음과 같습니다 : bs4, urllib, pytube, pydub, eyed3
import requests
from bs4 import BeautifulSoup
import sys
import urllib.request
import urllib.parse
import re
import os
import time
from pytube import YouTube
from pydub import AudioSegment
AudioSegment.ffmpeg = r"C:\\FFmpeg\\bin\\ffmpeg.exe"
import eyed3
global input_path
global output_path
input_path = "/Temp"
output_path = "/Users/andyy/OneDrive - w/바탕 화면/songs"
melon_url="http://kko.to/IU8zwNmjM" #여기에 여러분의 플레이리스트 링크를 입력해 주세요
k = requests.get(melon_url,headers={"User-Agent":"Mozilla/5.0"})
key = k.url.split('plylstSeq=')[1]
key = key.split('&ref')[0]
print('Your playlist key is : '+key)
url = 'https://www.melon.com/mymusic/playlist/mymusicplaylistview_listSong.htm?plylstSeq='+str(key)
r = requests.get(url,headers={"User-Agent":"Mozilla/5.0"})
soup = BeautifulSoup(r.text,"html.parser")
def song_syntax_fixer(song):
song=song.replace("'",'')
song=song.replace(".",'')
song=song.replace("<",'')
song=song.replace(">",'')
song=song.replace(":",'')
song=song.replace('"','')
song=song.replace("/",'')
song=song.replace("|",'')
song=song.replace("?",'')
song=song.replace("*",'')
return song
def get_top_url(song,artist_name):
query_string = urllib.parse.urlencode({"search_query" : song+' '+artist_name+' lyrics'})
html_content = urllib.request.urlopen("http://www.youtube.com/results?" + query_string)
search_results = re.findall(r'href=\"\/watch\?v=(.{11})', html_content.read().decode())
while search_results==[]:
print("disconnected, trying again...")
time.sleep(1)
query_string = urllib.parse.urlencode({"search_query" : song+' '+artist_name+' lyrics'})
html_content = urllib.request.urlopen("http://www.youtube.com/results?" + query_string)
search_results = re.findall(r'href=\"\/watch\?v=(.{11})', html_content.read().decode())
print('link obtained, connecting...')
youtube_url="http://www.youtube.com/watch?v=" + search_results[0]
return youtube_url
def download_high_audio(youtube_url,song):
yt=YouTube(youtube_url)
stream = yt.streams.filter(only_audio=True).order_by('abr')[-1]
bit_rate=getattr(stream,'abr')
print(bit_rate)
stream.download(input_path,song)
print('downloaded, converting...')
def convert(youtube_url,song):
sound = AudioSegment.from_file(input_path+"/"+song+'.webm')
sound.export(output_path+"/"+song+".mp3", format="mp3", bitrate='160k')
def get_album_art_high(song,artist_name,album):
API_KEY = 'b73672ba11b09300fdf7bcd2a2db1863'
song=song.split('(')[0]
artist_name=artist_name.split('(')[0]
headers = {
'user-agent': 'Mozilla/5.0'
}
payload = {
'api_key': API_KEY,
'method': 'album.getinfo',
'artist': artist_name,
'album': album,
'autocorrect':'1',
'format': 'json'
}
r = requests.get('http://ws.audioscrobbler.com/2.0/', headers=headers, params=payload)
try:
return r.json()['album']['image'][3]['#text']
except KeyError:
return ''
def get_album_art_low(song,artist_name,album):
API_KEY = 'b73672ba11b09300fdf7bcd2a2db1863'
song=song.split('(')[0]
artist_name=artist_name.split('(')[0]
headers = {
'user-agent': 'Mozilla/5.0'
}
payload = {
'api_key': API_KEY,
'method': 'album.search',
'limit': '1',
'album': album,
'format': 'json'
}
r = requests.get('http://ws.audioscrobbler.com/2.0/', headers=headers, params=payload)
try:
return r.json()['results']['albummatches']['album'][0]['image'][3]['#text']
except KeyError:
return ''
def get_music_inf(song,artist_name,album):
API_KEY = 'b73672ba11b09300fdf7bcd2a2db1863'
song=song.split('(')[0]
artist_name=artist_name.split('(')[0]
headers = {
'user-agent': 'Mozilla/5.0'
}
payload = {
'api_key': API_KEY,
'method': 'track.getinfo',
'autocorrect':'1',
'track' : song,
'artist': artist_name,
'format': 'json'
}
r = requests.get('http://ws.audioscrobbler.com/2.0/', headers=headers, params=payload)
try:
return r.json()['track']['album']['image'][3]['#text']
except KeyError:
return ''
def high_audio(soup):
for item in soup.select("tr:has(#artistName)"):
artist_name = item.select_one("#artistName > a[href*='goArtistDetail']")['title']
song = item.select_one("a[href*='playSong']")['title']
album = item.select_one("a[href*='javascript:melon.link.goAlbumDetail']")['title']
artist_name = artist_name.split(" - ")[0]
song = song.split(' 재생 - 새 창')[0]
album = album.split(' - 페이지 이동')[0]
song=song_syntax_fixer(song)
print(song+" : "+artist_name+" : "+album)
youtube_url=get_top_url(song,artist_name)
# print(youtube_url)
download_high_audio(youtube_url,song)
convert(youtube_url,song)
print('converting finished, applying metadata...')
song_file = eyed3.load(output_path+"/"+song+".mp3")
song_file.tag.artist = artist_name
song_file.tag.album = album
print('searching music...')
art=get_music_inf(song,artist_name,album)
if art=='':
art=get_album_art_high(song,artist_name,album)
if art=='':
art=get_album_art_low(song,artist_name,album)
if art=='':
print('****************************No artwork availiable****************************')
try:
response = requests.get(art)
imagedata = response.content
song_file.tag.images.set(3,imagedata,"image/png",u"None")
song_file.tag.save()
except requests.exceptions.MissingSchema:
pass
song_file.tag.save()
print('done')
high_audio(soup)
다음 코드가 작동하는 원리는 다음과 같습니다
1. 멜론 플레이리스트 페이지에 들어간다
2. html 코드에서 플레이리스트를 가져온다
3. youtube에 노래 검색후 다운받는다
4. 노래를 mp3파일로 변환한다
5. last.fm 에 노래를 검색하고 앨범 아트를 가져온다
6. mp3파일에 앨범 아트 및 다른 metadata를 입력하고 저장한다
이 코드를 실행해 보았을때 거의 완벽하게 노래와 앨범아트가 다운받아지는 것으로 보아, 꽤 정확하다고 할 수 있습니다.
에러 및 사용방식에 대한 질문은 뎃글로 남겨주세요
**이 코드는 비영리적인 목적을 위해서라면 마음대로 퍼가셔도 됩니다