def feed_playlist(username): """Fetch user playlists when using the -u option.""" playlists = spotify.user_playlists(username) links = [] check = 1 while True: for playlist in playlists['items']: # in rare cases, playlists may not be found, so playlists['next'] # is None. Skip these. Also see Issue #91. if playlist['name'] is not None: print(u'{0:>5}. {1:<30} ({2} tracks)'.format( check, playlist['name'], playlist['tracks']['total'])) links.append(playlist) check += 1 if playlists['next']: playlists = spotify.next(playlists) else: break print('') playlist = misc.input_link(links) print('') write_playlist(playlist)
def feed_playlist(username): # fetch all user playlists playlists = spotify.user_playlists(username) links = [] check = 1 # iterate over user playlists for playlist in playlists['items']: print(str(check) + '. ' + misc.fix_encoding(playlist['name']) + ' (' + str(playlist['tracks']['total']) + ' tracks)') links.append(playlist) check += 1 print('') # let user select playlist playlist = misc.input_link(links) # fetch detailed information for playlist results = spotify.user_playlist(playlist['owner']['id'], playlist['id'], fields="tracks,next") print('') # slugify removes any special characters file = slugify(playlist['name'], ok='-_()[]{}') + '.txt' print('Feeding ' + str(playlist['tracks']['total']) + ' tracks to ' + file) tracks = results['tracks'] # write tracks to file misc.feed_tracks(file, tracks) # check if there are more pages # 1 page = 50 results while tracks['next']: tracks = spotify.next(tracks) misc.feed_tracks(file, tracks)
def generate_youtube_url(raw_song): """Search for the song on YouTube and generate a URL to its video.""" meta_tags = generate_metadata(raw_song) if meta_tags is None: song = raw_song search_url = misc.generate_search_url(song, viewsort=False) else: song = generate_songname(meta_tags) search_url = misc.generate_search_url(song, viewsort=True) item = urllib.request.urlopen(search_url).read() # item = unicode(item, 'utf-8') items_parse = BeautifulSoup(item, "html.parser") videos = [] for x in items_parse.find_all( 'div', {'class': 'yt-lockup-dismissable yt-uix-tile'}): # confirm the video result is not an advertisement if x.find('channel') is None and x.find('googleads') is None: y = x.find('div', class_='yt-lockup-content') link = y.find('a')['href'] title = y.find('a')['title'] try: videotime = x.find('span', class_="video-time").get_text() except AttributeError: return generate_youtube_url(raw_song) youtubedetails = { 'link': link, 'title': title, 'videotime': videotime, 'seconds': misc.get_sec(videotime) } videos.append(youtubedetails) if meta_tags is None: break if not videos: return None if args.manual: print(song) print('') print('0. Skip downloading this song') # fetch all video links on first page on YouTube for i, v in enumerate(videos): print(u'{0}. {1} {2} {3}'.format(i + 1, v['title'], v['videotime'], "http://youtube.com" + v['link'])) print('') # let user select the song to download result = misc.input_link(videos) if result is None: return None else: if meta_tags is not None: videos.sort(key=lambda x: abs(x['seconds'] - (int(meta_tags[ 'duration_ms']) / 1000))) result = videos[0] full_link = u'youtube.com{0}'.format(result['link']) return full_link
def generate_YouTube_URL(raw_song): # decode spotify http link to "[artist] - [song]" song = generate_songname(raw_song) # generate direct search YouTube URL searchURL = misc.generate_search_URL(song) item = urllib2.urlopen(searchURL).read() #item = unicode(item, 'utf-8') items_parse = BeautifulSoup(item, "html.parser") check = 1 if args.manual: links = [] print(song) print('') print('0. Skip downloading this song') # fetch all video links on first page on YouTube for x in items_parse.find_all('h3', {'class': 'yt-lockup-title'}): # confirm the video result is not an advertisement if not x.find('channel') == -1 or not x.find('googleads') == -1: print(str(check) + '. ' + x.get_text()) links.append(x.find('a')['href']) check += 1 print('') # let user select the song to download result = misc.input_link(links) if result is None: return None else: # get video link of the first YouTube result result = items_parse.find_all(attrs={'class': 'yt-uix-tile-link'})[0]['href'] # confirm the video result is not an advertisement # otherwise keep iterating until it is not while not result.find('channel') == -1 or not result.find('googleads') == -1: result = items_parse.find_all(attrs={'class': 'yt-uix-tile-link'})[check]['href'] check += 1 full_link = "youtube.com" + result return full_link
def generate_youtube_url(raw_song, meta_tags, tries_remaining=5): """Search for the song on YouTube and generate a URL to its video.""" # prevents an infinite loop but allows for a few retries if tries_remaining == 0: return if meta_tags is None: song = raw_song search_url = misc.generate_search_url(song, viewsort=False) else: song = generate_songname(meta_tags) search_url = misc.generate_search_url(song, viewsort=True) item = urllib.request.urlopen(search_url).read() # item = unicode(item, 'utf-8') items_parse = BeautifulSoup(item, "html.parser") videos = [] for x in items_parse.find_all( 'div', {'class': 'yt-lockup-dismissable yt-uix-tile'}): # ensure result is not a channel if x.find('channel' ) is not None or 'yt-lockup-channel' in x.parent.attrs[ 'class'] or 'yt-lockup-channel' in x.attrs['class']: continue # ensure result is not a mix/playlist if 'yt-lockup-playlist' in x.parent.attrs['class']: continue # confirm the video result is not an advertisement if x.find('googleads') is not None: continue y = x.find('div', class_='yt-lockup-content') link = y.find('a')['href'] title = y.find('a')['title'] try: videotime = x.find('span', class_="video-time").get_text() except AttributeError: return generate_youtube_url(raw_song, meta_tags, tries_remaining - 1) youtubedetails = { 'link': link, 'title': title, 'videotime': videotime, 'seconds': misc.get_sec(videotime) } videos.append(youtubedetails) if meta_tags is None: break if not videos: return None if args.manual: print(song) print('') print('0. Skip downloading this song') # fetch all video links on first page on YouTube for i, v in enumerate(videos): print(u'{0}. {1} {2} {3}'.format(i + 1, v['title'], v['videotime'], "http://youtube.com" + v['link'])) print('') # let user select the song to download result = misc.input_link(videos) if result is None: return None else: if meta_tags is not None: # filter out videos that do not have a similar length to the Spotify song duration_tolerance = 10 max_duration_tolerance = 20 possible_videos_by_duration = list() ''' start with a reasonable duration_tolerance, and increment duration_tolerance until one of the Youtube results falls within the correct duration or the duration_tolerance has reached the max_duration_tolerance ''' while len(possible_videos_by_duration) == 0: possible_videos_by_duration = list( filter( lambda x: abs(x['seconds'] - (int(meta_tags[ 'duration_ms']) / 1000)) <= duration_tolerance, videos)) duration_tolerance += 1 if duration_tolerance > max_duration_tolerance: print(meta_tags['name'], 'by', meta_tags['artists'][0]['name'], 'was not found') return None result = possible_videos_by_duration[0] else: # if the metadata could not be acquired, take the first result from Youtube because the proper song length is unknown result = videos[0] full_link = None if result: full_link = u'youtube.com{0}'.format(result['link']) return full_link