Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

添加genre和lyric tag #9

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 16 additions & 3 deletions ncm/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from ncm.constants import get_album_url
from ncm.constants import get_artist_url
from ncm.constants import get_playlist_url
from ncm.constants import get_lyric_url


class CloudApi(object):
Expand Down Expand Up @@ -49,6 +50,21 @@ def get_song(self, song_id):

return result['songs'][0]

def get_lyric(self, song_id):
"""
Get song lyric by song id
:param song_id:
:return:
"""
url = get_lyric_url(song_id)
result = self.get_request(url)
try:
return result['lrc']['lyric']
except:
return ''



def get_album_songs(self, album_id):
"""
Get all album songs info by album id
Expand Down Expand Up @@ -92,6 +108,3 @@ def get_playlist_songs(self, playlist_id):
url = get_playlist_url(playlist_id)
result = self.get_request(url)
return result['result']['tracks'], result['result']['name']



3 changes: 3 additions & 0 deletions ncm/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,6 @@ def get_artist_url(artist_id):

def get_playlist_url(playlist_id):
return 'http://music.163.com/api/playlist/detail?id={}'.format(playlist_id)

def get_lyric_url(song_id):
return 'http://music.163.com/api/song/lyric?id={}&lv=1'.format(song_id)
20 changes: 15 additions & 5 deletions ncm/downloader.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,21 @@
from ncm.file_util import add_metadata_to_song


def download_song_by_id(song_id, download_folder, sub_folder=True):
def download_song_by_id(song_id, download_folder, gener, sub_folder=True):
# get song info
api = CloudApi()
song = api.get_song(song_id)
download_song_by_song(song, download_folder, sub_folder)
download_song_by_song(song, download_folder, gener, sub_folder)


def download_song_by_song(song, download_folder, sub_folder=True):
def download_song_by_song(song, download_folder, gener, sub_folder=True):
# get song info
api = CloudApi()
song_id = song['id']
song_name = re.sub(r'[\\/:*?"<>|]', ' ', song['name']) # Replace illegal character with ' '
artist_name = song['artists'][0]['name']
album_name = song['album']['name']
lyric = api.get_lyric(song_id)

# update song file name by config
song_file_name = '{}.mp3'.format(song_name)
Expand Down Expand Up @@ -58,15 +59,24 @@ def download_song_by_song(song, download_folder, sub_folder=True):
cover_url = song['album']['blurPicUrl']
cover_file_name = 'cover_{}.jpg'.format(song_id)
download_file(cover_url, cover_file_name, song_download_folder)

write_file(lyric, song_file_name.replace(".mp3", ".lrc"), song_download_folder)
# add metadata for song
song_file_path = os.path.join(song_download_folder, song_file_name)
cover_file_path = os.path.join(song_download_folder, cover_file_name)
add_metadata_to_song(song_file_path, cover_file_path, song)
add_metadata_to_song(song_file_path, cover_file_path, song, gener, lyric)

# delete cover file
os.remove(cover_file_path)

def write_file(lyric, file_name, folder):

if not os.path.exists(folder):
os.makedirs(folder)
file_path = os.path.join(folder, file_name)
lrc_file = open(file_path,'w')
lrc_file.write(lyric)
lrc_file.close()
return False

def download_file(file_url, file_name, folder):

Expand Down
49 changes: 46 additions & 3 deletions ncm/file_util.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# -*- coding: utf-8 -*-

from mutagen.mp3 import MP3, HeaderNotFoundError
from mutagen.id3 import ID3, APIC, TPE1, TIT2, TALB, error
from mutagen.id3 import ID3, APIC, TPE1, TIT2, TALB, TCON, USLT, SYLT, error
import time,datetime,re


def add_metadata_to_song(file_path, cover_path, song):
def add_metadata_to_song(file_path, cover_path, song, gener, lyric):
# If no ID3 tags in mp3 file
try:
audio = MP3(file_path, ID3=ID3)
Expand Down Expand Up @@ -44,6 +44,49 @@ def add_metadata_to_song(file_path, cover_path, song):
text=song['artists'][0]['name']
)
)
# add genre
id3.add(
TCON(
encoding=3,
text=gener
)
)
# add Unsychronised lyric
id3.add(
USLT(
encoding=3,
lang='chs',
desc="Unsychronised lyric",
text=lyric
)
)
# add Synchronized lyric
sync_lyric = []
for line in lyric.split("\n"):
#print(line)
if line.find("]") != -1:
time_str = line.split("]")[0].replace("[","")
lyric_str = line.split("]")[1]
try:
time_array = re.findall(r"\d+:\d+\.\d+", time_str)
if len(time_array) == 1:
time_m = int(time_array[0].split(":")[0])
time_s = int(time_array[0].split(":")[1].split(".")[0])
time_ms = int(time_array[0].split(":")[1].split(".")[1])
sync_lyric.append((lyric_str,time_m*60*1000+time_s*1000+time_ms))
except:
print(time_str)

id3.add(
SYLT(
encoding=3,
lang='chs',
format=2,
type=1,
desc="Synchronized lyric",
text=sync_lyric
)
)
# add song name
id3.add(
TIT2(
Expand Down
10 changes: 5 additions & 5 deletions ncm/start.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def download_hot_songs(artist_id):
download_count = config.DOWNLOAD_HOT_MAX if (0 < config.DOWNLOAD_HOT_MAX < 50) else config.DOWNLOAD_HOT_MAX_DEFAULT
for i, song in zip(range(download_count), songs):
print(str(i + 1) + ' song name:' + song['name'])
download_song_by_song(song, folder_path, False)
download_song_by_song(song, folder_path, songs[0]['artists'][0]['name'], False)


def download_album_songs(album_id):
Expand All @@ -29,7 +29,7 @@ def download_album_songs(album_id):
folder_path = os.path.join(config.DOWNLOAD_DIR, folder_name)
for i, song in enumerate(songs):
print(str(i + 1) + ' song name:' + song['name'])
download_song_by_song(song, folder_path, False)
download_song_by_song(song, folder_path, songs[0]['album']['name'], False)


def download_playlist_songs(playlist_id):
Expand All @@ -38,7 +38,7 @@ def download_playlist_songs(playlist_id):
folder_path = os.path.join(config.DOWNLOAD_DIR, folder_name)
for i, song in enumerate(songs):
print(str(i + 1) + ' song name:' + song['name'])
download_song_by_song(song, folder_path, False)
download_song_by_song(song, folder_path, playlist_name, False)


def get_parse_id(song_id):
Expand All @@ -63,10 +63,10 @@ def main():
help='Download a playlist all songs by playlist_id')
args = parser.parse_args()
if args.song_id:
download_song_by_id(get_parse_id(args.song_id), config.DOWNLOAD_DIR)
download_song_by_id(get_parse_id(args.song_id), config.DOWNLOAD_DIR, '')
elif args.song_ids:
for song_id in args.song_ids:
download_song_by_id(get_parse_id(song_id), config.DOWNLOAD_DIR)
download_song_by_id(get_parse_id(song_id), config.DOWNLOAD_DIR, '')
elif args.artist_id:
download_hot_songs(get_parse_id(args.artist_id))
elif args.album_id:
Expand Down