Last active
March 20, 2023 12:46
-
-
Save syxanash/f9a21f21d2bbad43d7eae0f969efe0b6 to your computer and use it in GitHub Desktop.
lyrics downloader from genius.com with API+Scraping 🏴☠️
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'rest-client' | |
require 'nokogiri' | |
require 'genius' | |
require 'similar_text' | |
require 'optparse' | |
GENIUS_CLIENT_TOKEN = 'YOUR API TOKEN GOES HERE!!!'.freeze | |
class LyricsNotFound < StandardError; end | |
class LyricsFinder | |
# change this constant if you want to increase or decrease the percentage | |
# of similarity between the artist entered by the user and the artist | |
# found on genius.com | |
PERCENTAGE_OF_SIMILARITY = 80 | |
def initialize(api_key) | |
Genius.access_token = api_key | |
end | |
def lyrics(track_name, track_artist) | |
# beautify the song name removing the featuring in order to be easily | |
# searchable on genius.com | |
track_name.gsub!(/\((.*?)\)/, '') | |
track_artist.gsub!(/\((.*?)\)/, '') | |
track_name.gsub!(/.((ft\.|feat).*?)$/mi, '') | |
track_artist.gsub!(/.((ft\.|feat).*?)$/mi, '') | |
songs = Genius::Song.search("#{track_artist} #{track_name}") | |
song_found = songs.first | |
# if first method returns nil or song artist found is not similar by 80% | |
# to the artist entered by the user then lyrics is not found | |
if song_found.nil? || | |
(song_found.resource['primary_artist']['name'].downcase.similar(track_artist.downcase) < PERCENTAGE_OF_SIMILARITY) | |
raise LyricsNotFound, "Lyrics not found for #{track_name}" | |
end | |
# download html content from the genius.com website and parse the div | |
# lyrics downloading only the text removing extra tags | |
html_content = RestClient.get(song_found.url) | |
doc = Nokogiri::HTML::Document.parse(html_content) | |
div = doc.at_css('div[data-lyrics-container=true]') | |
div.css('br').each do |node| | |
node.replace(Nokogiri::XML::Text.new("\n", div)) | |
end | |
div.text | |
end | |
end | |
options = {} | |
OptionParser.new do |opts| | |
opts.banner = 'Usage: ruby genio.rb [options]' | |
opts.on('-n', '--name=NAME', 'Track name') { |value| options[:name] = value } | |
opts.on('-a', '--artist=NAME', 'Artist name') { |value| options[:artist] = value } | |
opts.on('-h', '--help', 'Show this awesome help') { puts opts; exit } | |
end.parse! | |
if options[:name].nil? || options[:artist].nil? | |
abort('Specify artist and track name, check genio.rb --help') | |
end | |
finder = LyricsFinder.new(GENIUS_CLIENT_TOKEN) | |
begin | |
lyrics = finder.lyrics(options[:name], options[:artist]) | |
puts lyrics | |
rescue LyricsNotFound | |
puts 'Lyrics not found on genius.com' | |
rescue Genius::AuthenticationError | |
puts 'Error occurred while using genius.com API' | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment