Skip to content

Instantly share code, notes, and snippets.

@syxanash
Last active March 20, 2023 12:46
Show Gist options
  • Save syxanash/f9a21f21d2bbad43d7eae0f969efe0b6 to your computer and use it in GitHub Desktop.
Save syxanash/f9a21f21d2bbad43d7eae0f969efe0b6 to your computer and use it in GitHub Desktop.
lyrics downloader from genius.com with API+Scraping 🏴‍☠️
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