def to_json(self, filename=None, sanitize=True): """Converts the Song object to a json string. Args: filename (:obj:`str`): Output filename, a string. If not specified, the result is returned as a string. sanitize (:obj:`bool`): Sanitizes the filename if `True`. Returns: :obj:`str` \\| :obj:`None`: If :obj:`filename` is `None`, returns the lyrics as a plain string, otherwise `None`. Warning: If you set :obj:`sanitize` to `False`, the file name may contain invalid characters, and thefore cause the saving to fail. """ data = self._body data['songs'] = [song._body for song in self.songs] # Return the json string if no output path was specified if not filename: return json.dumps(data, indent=1) # Save Song object to a json file filename = sanitize_filename(filename) if sanitize else filename with open(filename, 'w') as ff: json.dump(data, ff, indent=1) return None
def to_text(self, filename=None, binary_encoding=False, sanitize=True): """ Convert all song lyrics to a single string. INPUT :filename: Output filename, string. If not specified, the result is returned as a string. :binary_encoding: Enable binary encoding of text data. :sanitize: Sanitizes the filename if True. OUTPUT If `filename` is None, returns the lyrics as a plain string. Otherwise None. """ data = ' '.join(song.lyrics for song in self.songs) # Return the lyrics as a string if no `filename` was specified if not filename: return data # Save song lyrics to a text file filename = sanitize_filename(filename) if sanitize else filename with open(filename, 'wb' if binary_encoding else 'w') as ff: if binary_encoding: data = data.encode('utf8') ff.write(data) return None
def to_text(self, filename=None, binary_encoding=False, sanitize=True): """Converts all song lyrics to a single string. Args: filename (:obj:`str`): Output filename, a string. If not specified, the result is returned as a string. binary_encoding (:obj:`bool`): Enables binary encoding of text data. sanitize (:obj:`bool`): Sanitizes the filename if `True`. Returns: :obj:`str` \\| :obj:`None`: If :obj:`filename` is `None`, returns the lyrics as a plain string. Otherwise `None`. Warning: If you set :obj:`sanitize` to `False`, the file name may contain invalid characters, and thefore cause the saving to fail. """ data = ' '.join(song.lyrics for song in self.songs) # Return the lyrics as a string if no `filename` was specified if not filename: return data # Save song lyrics to a text file filename = sanitize_filename(filename) if sanitize else filename with open(filename, 'wb' if binary_encoding else 'w') as ff: if binary_encoding: data = data.encode('utf8') ff.write(data) return None
def to_text(self, filename=None, binary_encoding=False, sanitize=True): """Save the song lyrics as a text file. INPUT :filename: Output filename. If not specified, the result is return as a string. :binary_encoding: Enable binary encoding of text data. :sanitize: Sanitizes the filename if True. OUTPUT If `filename` is None, returns the lyrics as a plain string. Otherwise None. """ data = self.lyrics # Return the lyrics as a string if no `filename` was specified if not filename: return data # Save song lyrics to a text file filename = sanitize_filename(filename) if sanitize else filename with open(filename, "wb" if binary_encoding else "w") as ff: if binary_encoding: data = data.encode("utf8") ff.write(data) return None
def to_json(self, filename=None, sanitize=True, ensure_ascii=True): """Converts the Song object to a json string. Args: filename (:obj:`str`, optional): Output filename, a string. If not specified, the result is returned as a string. sanitize (:obj:`bool`, optional): Sanitizes the filename if `True`. ensure_ascii (:obj:`bool`, optional): If ensure_ascii is true (the default), the output is guaranteed to have all incoming non-ASCII characters escaped. Returns: :obj:`str` \\| :obj:`None`: If :obj:`filename` is `None`, returns the lyrics as a plain string, otherwise `None`. Warning: If you set :obj:`sanitize` to `False`, the file name may contain invalid characters, and thefore cause the saving to fail. """ data = self._body data['songs'] = [song._body for song in self.songs] # Return the json string if no output path was specified if not filename: return json.dumps(data, indent=1, ensure_ascii=ensure_ascii) # Save Song object to a json file filename = sanitize_filename(filename) if sanitize else filename with open(filename, 'w') as ff: json.dump(data, ff, indent=1, ensure_ascii=ensure_ascii) return None
def get_and_process_songs(args): if args.artist_name is None and args.download_lyrics: print('\n********** ERROR *************') print('Invalid or missing artist name.') print('\n******************************\n') sys.exit() if args.download_lyrics: start = datetime.now(tz=TIMEZONE) stock_filename = 'Lyrics_' + args.artist_name.replace(' ', '') + '.json' stock_filename = sanitize_filename(stock_filename) print('{}| Beginning download'.format(start)) genius = lyricsgenius.Genius(GENIUS_ACCESS_TOKEN, sleep_time=1) artist_tracks = force_search_artist(genius, args.artist_name, sleep_time=600, max_songs=None, sort='popularity', per_page=20, get_full_info=True, allow_name_change=True) print('{}| Finished download in {}'.format(datetime.now(tz=TIMEZONE), datetime.now(tz=TIMEZONE) - start)) artist_tracks.save_lyrics() if args.load_path: if os.path.isdir(args.load_path): print('{}| Preparing mixed lyrics files'.format(datetime.now(tz=TIMEZONE))) text_and_target_from_dir(args.load_path, args.lookback) print('{}| Finished.'.format(datetime.now(tz=TIMEZONE))) sys.exit() else: genius_file = read_json(args.load_path) else: genius_file = read_json('./'+stock_filename) if not args.download_only: artist_lyrics = get_lyrics_from_json(genius_file, SONG_PART_REGEX) create_text_and_target(artist_lyrics, lookback=args.lookback)
def determine_filenames(self, extension): expected_filenames = [] for song in self.artist.songs: fn = "lyrics_{name}_{song}.{ext}".format(name=self.artist.name, song=song.title, ext=extension) fn = sanitize_filename(fn.lower().replace(" ", "")) expected_filenames.append(fn) return expected_filenames
def save_lyrics( self, filename=None, extension="json", overwrite=None, binary_encoding=False, full_data=True, sanitize=True, verbose=True, ): """Save Song lyrics and metadata to a JSON or TXT file.""" extension = extension.lstrip(".").lower() assert (extension == "json") or ( extension == "txt" ), "extension must be JSON or TXT" # Determine the filename if filename: for ext in ["txt", "TXT", "json", "JSON"]: filename = filename.replace("." + ext, "") filename += "." + extension else: filename = "Lyrics_{}_{}.{}".format( self.artist.replace(" ", ""), self.title.replace(" ", ""), extension ).lower() filename = sanitize_filename(filename) if sanitize else filename # Check if file already exists write_file = False if overwrite or not os.path.isfile(filename): write_file = True elif verbose: if ( input("{} already exists. Overwrite?\n(y/n): ".format(filename)).lower() == "y" ): write_file = True # Exit if we won't be saving a file if not write_file: if verbose: print("Skipping file save.\n") return # Save the lyrics to a file if extension == "json": self.to_json(filename, full_data=full_data) else: self.to_text(filename, binary_encoding=binary_encoding) if verbose: print("Wrote {} to {}.".format(self.title, filename)) return None
def save_lyrics( self, filename=None, extension="json", overwrite=False, binary_encoding=False, sanitize=True, verbose=True, ): """Saves all lyrics within an Artist object to a single file.""" extension = extension.lstrip(".").lower() assert (extension == "json") or (extension == "txt"), "extension must be JSON or TXT" # Determine the filename if not filename: filename = "Lyrics_" + self.name.replace(" ", "") + "." + extension filename = sanitize_filename(filename) if sanitize else filename # Check if file already exists write_file = False if overwrite or not os.path.isfile(filename): write_file = True elif verbose: if (input("{} already exists. Overwrite?\n(y/n): ".format( filename)).lower() == "y"): write_file = True # Exit if we won't be saving a file if not write_file: if verbose: print("Skipping file save.\n") return # Save the lyrics to a file if extension == "json": self.to_json(filename) else: self.to_text(filename, binary_encoding=binary_encoding) if verbose: print("Wrote `{}`".format(filename)) return None
def to_json(self, filename=None, sanitize=True): """ Convert the Song object to a json string. INPUT :filename: Output filename, string. If not specified, the result is returned as a string. :sanitize: Sanitizes the filename if True. OUTPUT If `filename` is None, returns the lyrics as a plain string. Otherwise None. """ data = self._body data['songs'] = [song._body for song in self.songs] # Return the json string if no output path was specified if not filename: return json.dumps(data, indent=1) # Save Song object to a json file filename = sanitize_filename(filename) if sanitize else filename with open(filename, 'w') as ff: json.dump(data, ff, indent=1) return None
def to_json(self, filename=None, full_data=True, sanitize=True): """ Convert the Song object to a json string. INPUT :filename: Output filename, string. If not specified, the result is returned as a string. :full_data: Provides full song metadata when set to True. :sanitize: Sanitizes the filename if True. OUTPUT If `filename` is None, returns the lyrics as a plain string. Otherwise None. """ data = self._body if full_data else self.to_dict() # Return the json string if no output path was specified if not filename: return json.dumps(data, indent=1) # Save Song object to a json file filename = sanitize_filename(filename) if sanitize else filename with open(filename, 'w') as ff: json.dump(data, ff, indent=1) return None
def save_lyrics(self, filename=None, extension='json', overwrite=False, binary_encoding=False, sanitize=True, verbose=True): """Saves all lyrics within an Artist object to a single file. If the extension is 'json', the method will save artist information and artist songs. If you only want the songs lyrics, set :obj:`extension` to `txt`. If you choose to go with JSON (which is the default extension), you can access the lyrics by accessing the :class:`Song <lyricsgenius.song.Song>` objects inside the `songs` key of the JSON file. Take a look at the example below. Args: filename (:obj:`str`): Output filename, a string. If not specified, the result is returned as a string. extension (:obj:`str`): Format of the file (`json` or `txt`). overwrite (:obj:`bool`, optional): Overwrites preexisting file if `True`. Otherwise prompts user for input. binary_encoding (:obj:`bool`): Enables binary encoding of text data. sanitize (:obj:`bool`): Sanitizes the filename if `True`. verbose (:obj:`bool`): prints operation result. Examples: .. code:: python # getting songs lyrics from saved JSON file import json with open('file.json', 'r') as f: data = json.load(f) for song in data['songs']: print(song.lyrics) Warning: If you set :obj:`sanitize` to `False`, the file name may contain invalid characters, and thefore cause the saving process to fail. """ extension = extension.lstrip(".").lower() msg = "extension must be JSON or TXT" assert (extension == 'json') or (extension == 'txt'), msg # Determine the filename if not filename: filename = 'Lyrics_' + self.name.replace(' ', '') + '.' + extension filename = sanitize_filename(filename) if sanitize else filename # Check if file already exists write_file = False if overwrite or not os.path.isfile(filename): write_file = True elif verbose: msg = "{} already exists. Overwrite?\n(y/n): ".format(filename) if input(msg).lower() == 'y': write_file = True # Exit if we won't be saving a file if not write_file: if verbose: print('Skipping file save.\n') return # Save the lyrics to a file if extension == 'json': self.to_json(filename) else: self.to_text(filename, binary_encoding=binary_encoding) if verbose: print('Wrote `{}`'.format(filename)) return None
def save_lyrics(self, filename=None, extension='json', overwrite=None, binary_encoding=False, ensure_ascii=True, full_data=True, sanitize=True, verbose=True): """Save Song lyrics and metadata to a JSON or TXT file. If the extension is 'json' (which the default), the lyrics will be saved alongside the song's information. Take a look at the example below. Args: filename (:obj:`str`, optional): Output filename, a string. If not specified, the result is returned as a string. extension (:obj:`str`, optional): Format of the file (`json` or `txt`). overwrite (:obj:`bool`, optional): Overwrites preexisting file if `True`. Otherwise prompts user for input. binary_encoding (:obj:`bool`, optional): Enables binary encoding of text data. ensure_ascii (:obj:`bool`, optional): If ensure_ascii is true (the default), the output is guaranteed to have all incoming non-ASCII characters escaped. full_data (:obj:`str`): Provides full song metadata when set to `True`. sanitize (:obj:`bool`, optional): Sanitizes the filename if `True`. verbose (:obj:`bool`, optional): prints operation result. Examples: .. code:: python # getting songs lyrics from saved JSON file import json with open('song.json', 'r') as f: data = json.load(f) print(data['lyrics']) Note: If :obj:`full_data` is set to `False`, only the following attributes of the song will be available: :obj:`title`, :attr:`album`, :attr:`year`, :attr:`lyrics`, and :attr:`song_art_image_url` Warning: If you set :obj:`sanitize` to `False`, the file name may contain invalid characters, and thefore cause the saving to fail. """ extension = extension.lstrip(".").lower() msg = "extension must be JSON or TXT" assert (extension == 'json') or (extension == 'txt'), msg # Determine the filename if filename: for ext in ["txt", "TXT", "json", "JSON"]: filename = filename.replace("." + ext, "") filename += "." + extension else: filename = "Lyrics_{}_{}.{}".format(self.artist.replace(" ", ""), self.title.replace(" ", ""), extension).lower() filename = sanitize_filename(filename) if sanitize else filename # Check if file already exists write_file = False if overwrite or not os.path.isfile(filename): write_file = True elif verbose: msg = "{} already exists. Overwrite?\n(y/n): ".format(filename) if input(msg).lower() == 'y': write_file = True # Exit if we won't be saving a file if not write_file: if verbose: print('Skipping file save.\n') return # Save the lyrics to a file if extension == 'json': self.to_json(filename, full_data=full_data, sanitize=sanitize, ensure_ascii=ensure_ascii) else: self.to_text(filename, binary_encoding=binary_encoding, sanitize=sanitize) if verbose: print('Wrote {} to {}.'.format(self.title, filename)) return None
def test_sanitize_filename(self): raw = 'B@ad File#_name' cleaned = 'Bad File_name' r = sanitize_filename(raw) self.assertEqual(r, cleaned)