blue_conductor 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +18 -2
- data/blue_conductor.gemspec +3 -3
- data/lib/blue_conductor.rb +21 -7
- data/lib/blue_conductor/.DS_Store +0 -0
- data/lib/blue_conductor/band_manager.rb +4 -7
- data/lib/blue_conductor/http/.DS_Store +0 -0
- data/lib/blue_conductor/http/record/.DS_Store +0 -0
- data/lib/blue_conductor/http/record/response.rb +19 -0
- data/lib/blue_conductor/http/record/sanitizer.rb +25 -0
- data/lib/blue_conductor/http/record/url_generator.rb +16 -0
- data/lib/blue_conductor/http/request.rb +10 -4
- data/lib/blue_conductor/http/song/.DS_Store +0 -0
- data/lib/blue_conductor/http/song/response.rb +22 -0
- data/lib/blue_conductor/http/song/sanitizer.rb +25 -0
- data/lib/blue_conductor/http/song/url_generator.rb +16 -0
- data/lib/blue_conductor/producer.rb +32 -0
- data/lib/blue_conductor/song.rb +2 -2
- data/lib/blue_conductor/version.rb +1 -1
- data/lyric +1 -0
- data/spec/blue_conductor/band_manager_spec.rb +10 -9
- data/spec/blue_conductor/producer_spec.rb +56 -0
- data/spec/blue_conductor_spec.rb +15 -2
- data/spec/cassettes/blue_conductor_album.yml +18719 -0
- data/spec/cassettes/blue_conductor_song.yml +2447 -0
- data/spec/cassettes/full_album.yml +20356 -0
- data/spec/cassettes/invalid_album.yml +461 -0
- data/spec/cassettes/invalid_song.yml +2382 -0
- data/spec/cassettes/song.yml +2167 -128
- metadata +23 -8
- data/lib/blue_conductor/http/response.rb +0 -11
- data/lib/blue_conductor/http/url_generator.rb +0 -14
- data/lib/blue_conductor/sanitizer.rb +0 -21
data/README.md
CHANGED
@@ -21,7 +21,7 @@ Or install it yourself as:
|
|
21
21
|
Usage is easy. Call .song_for on the BlueConductor object and pass in a band name and song title.
|
22
22
|
|
23
23
|
```ruby
|
24
|
-
BlueConductor.song_for('
|
24
|
+
BlueConductor.song_for('Van Halen', 'Panama')
|
25
25
|
```
|
26
26
|
|
27
27
|
|
@@ -30,9 +30,25 @@ Which will return a BlueConductor::Song object containing the following fields
|
|
30
30
|
* `title`
|
31
31
|
* `band`
|
32
32
|
* `lyrics`
|
33
|
+
* `album`
|
34
|
+
|
35
|
+
Calling title or band will return the information that you originally passed in to the BlueConductor. Calling .lyrics will return the lyrics of that song as provided by songlyrics.com. If the lyrics to a song you entered in either do not exist, are not on the songlyrics website or if there was a spelling error, then calling .lyrics will return a string saying 'Sorry we do not have the requested lyrics'. Calling .album will return the album that the song is on.
|
36
|
+
|
37
|
+
BlueConductor has a second method called .record_for. Simply pass in the band name and the name of your favorite album and it will return an array of song objects containing the information of each song.
|
38
|
+
|
39
|
+
```ruby
|
40
|
+
BlueConductor.record_for('Van Halen', '1984')
|
41
|
+
```
|
42
|
+
|
43
|
+
Now, this method returns a BlueConductor::Producer objects that has the following fields on it
|
44
|
+
|
45
|
+
* `title`
|
46
|
+
* `band`
|
47
|
+
* `songs`
|
48
|
+
* `image`
|
33
49
|
* `error`
|
34
50
|
|
35
|
-
|
51
|
+
Title and band are obviously set to the values that you pass in. The .songs field though returns an array of BlueConductor::Song objects each with specific information about each song on the album provided. .image contains the image source of the album art and the error field only contains a string if the album/band you provided is not on songlyrics.com.
|
36
52
|
|
37
53
|
##CLI
|
38
54
|
|
data/blue_conductor.gemspec
CHANGED
@@ -6,10 +6,10 @@ require "blue_conductor/version"
|
|
6
6
|
Gem::Specification.new do |gem|
|
7
7
|
gem.name = "blue_conductor"
|
8
8
|
gem.version = BlueConductor::VERSION
|
9
|
-
gem.authors = ["Alex Williams"
|
9
|
+
gem.authors = ["Alex Williams"]
|
10
10
|
gem.email = ["alexwilliams4@me.com"]
|
11
|
-
gem.description = %q{Scrapes
|
12
|
-
gem.summary = %q{
|
11
|
+
gem.description = %q{Scrapes songlyrics.com for song lyrics}
|
12
|
+
gem.summary = %q{songlyrics.com scraper}
|
13
13
|
gem.homepage = ""
|
14
14
|
|
15
15
|
gem.files = `git ls-files`.split($/)
|
data/lib/blue_conductor.rb
CHANGED
@@ -1,25 +1,39 @@
|
|
1
1
|
require 'open-uri'
|
2
2
|
require 'nokogiri'
|
3
|
+
require 'net/http'
|
3
4
|
|
4
5
|
require_relative 'blue_conductor/version'
|
5
6
|
require_relative 'blue_conductor/band_manager'
|
6
|
-
require_relative 'blue_conductor/
|
7
|
-
require_relative 'blue_conductor/http/request'
|
8
|
-
require_relative 'blue_conductor/http/response'
|
9
|
-
require_relative 'blue_conductor/http/url_generator'
|
7
|
+
require_relative 'blue_conductor/producer'
|
10
8
|
require_relative 'blue_conductor/song'
|
11
9
|
|
10
|
+
require_relative 'blue_conductor/http/request'
|
11
|
+
|
12
|
+
require_relative 'blue_conductor/http/song/sanitizer'
|
13
|
+
require_relative 'blue_conductor/http/song/response'
|
14
|
+
require_relative 'blue_conductor/http/song/url_generator'
|
15
|
+
|
16
|
+
require_relative 'blue_conductor/http/record/sanitizer'
|
17
|
+
require_relative 'blue_conductor/http/record/response'
|
18
|
+
require_relative 'blue_conductor/http/record/url_generator'
|
19
|
+
|
20
|
+
|
12
21
|
module BlueConductor
|
13
22
|
def self.song_for(band, song)
|
14
23
|
manager = BlueConductor::BandManager.new(band, song)
|
15
|
-
manager.url_generator = BlueConductor::HTTP::UrlGenerator
|
24
|
+
manager.url_generator = BlueConductor::HTTP::Song::UrlGenerator
|
16
25
|
manager.request = BlueConductor::HTTP::Request
|
17
|
-
manager.parser = BlueConductor::HTTP::Response
|
26
|
+
manager.parser = BlueConductor::HTTP::Song::Response
|
18
27
|
|
19
28
|
manager.song!
|
20
29
|
end
|
21
30
|
|
22
31
|
def self.record_for(band, record_title)
|
23
|
-
|
32
|
+
producer = BlueConductor::Producer.new(band, record_title)
|
33
|
+
producer.url_generator = BlueConductor::HTTP::Record::UrlGenerator
|
34
|
+
producer.request = BlueConductor::HTTP::Request
|
35
|
+
producer.parser = BlueConductor::HTTP::Record::Response
|
36
|
+
|
37
|
+
producer.record!
|
24
38
|
end
|
25
39
|
end
|
Binary file
|
@@ -1,12 +1,12 @@
|
|
1
1
|
module BlueConductor
|
2
2
|
class BandManager
|
3
|
-
attr_reader :band, :song, :data, :
|
3
|
+
attr_reader :band, :song, :data, :album
|
4
4
|
attr_accessor :url_generator, :request, :parser
|
5
5
|
|
6
6
|
def initialize(band, song)
|
7
7
|
@band = band
|
8
8
|
@song = song
|
9
|
-
@
|
9
|
+
@album = ''
|
10
10
|
@data = ''
|
11
11
|
end
|
12
12
|
|
@@ -14,11 +14,8 @@ module BlueConductor
|
|
14
14
|
url = url_generator.generate(self)
|
15
15
|
html = request.fetch(url)
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
else
|
20
|
-
@error = 'The band/song does not exist || there was a spelling error'
|
21
|
-
end
|
17
|
+
@data = parser.data(html)
|
18
|
+
@album = parser.album(html)
|
22
19
|
|
23
20
|
BlueConductor::Song.new(self)
|
24
21
|
end
|
Binary file
|
Binary file
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module BlueConductor
|
2
|
+
module HTTP
|
3
|
+
module Record
|
4
|
+
class Response
|
5
|
+
|
6
|
+
def self.parse(html)
|
7
|
+
doc = Nokogiri::HTML(html)
|
8
|
+
doc.css('.rightcol .tracklist td a').map(&:text)
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.parse_image(html)
|
12
|
+
doc = Nokogiri::HTML(html)
|
13
|
+
doc.css('.leftcol img')[0]['src']
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module BlueConductor
|
2
|
+
module HTTP
|
3
|
+
module Record
|
4
|
+
class Sanitizer
|
5
|
+
UNWANTED_CHARS = %r([^a-zA-Z0-9])
|
6
|
+
|
7
|
+
attr_reader :band, :title
|
8
|
+
|
9
|
+
def initialize(producer)
|
10
|
+
@band = producer.band
|
11
|
+
@title = producer.title
|
12
|
+
end
|
13
|
+
|
14
|
+
def clean
|
15
|
+
@band = strip(@band)
|
16
|
+
@title = strip(@title)
|
17
|
+
end
|
18
|
+
|
19
|
+
def strip(str)
|
20
|
+
str.downcase.gsub(UNWANTED_CHARS, "-")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module BlueConductor
|
2
|
+
module HTTP
|
3
|
+
module Record
|
4
|
+
class UrlGenerator
|
5
|
+
BASE_URI = "http://www.songlyrics.com/"
|
6
|
+
|
7
|
+
def self.generate(producer)
|
8
|
+
sanitizer = BlueConductor::HTTP::Record::Sanitizer.new(producer)
|
9
|
+
sanitizer.clean
|
10
|
+
|
11
|
+
"#{BASE_URI}#{sanitizer.band}/#{sanitizer.title}/"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -3,12 +3,18 @@ module BlueConductor
|
|
3
3
|
class Request
|
4
4
|
|
5
5
|
def self.fetch(url)
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
6
|
+
response = Net::HTTP.get_response(URI.parse(url))
|
7
|
+
|
8
|
+
if response.code == '301'
|
9
|
+
parse(response['location'])
|
10
|
+
else
|
11
|
+
parse(url)
|
10
12
|
end
|
11
13
|
end
|
14
|
+
|
15
|
+
def self.parse(location)
|
16
|
+
Net::HTTP.get(URI.parse(location))
|
17
|
+
end
|
12
18
|
end
|
13
19
|
end
|
14
20
|
end
|
Binary file
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module BlueConductor
|
2
|
+
module HTTP
|
3
|
+
module Song
|
4
|
+
class Response
|
5
|
+
|
6
|
+
def self.data(html)
|
7
|
+
doc = Nokogiri::HTML(html)
|
8
|
+
doc.css('p#songLyricsDiv').text
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.album(html)
|
12
|
+
doc = Nokogiri::HTML(html)
|
13
|
+
begin
|
14
|
+
doc.css('div.pagetitle a')[1].text
|
15
|
+
rescue
|
16
|
+
'Album Missing'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module BlueConductor
|
2
|
+
module HTTP
|
3
|
+
module Song
|
4
|
+
class Sanitizer
|
5
|
+
UNWANTED_CHARS = %r([^a-zA-Z0-9])
|
6
|
+
|
7
|
+
attr_reader :band, :song
|
8
|
+
|
9
|
+
def initialize(manager)
|
10
|
+
@band = manager.band
|
11
|
+
@song = manager.song
|
12
|
+
end
|
13
|
+
|
14
|
+
def clean
|
15
|
+
@band = strip(@band)
|
16
|
+
@song = strip(@song)
|
17
|
+
end
|
18
|
+
|
19
|
+
def strip(str)
|
20
|
+
str.downcase.gsub(UNWANTED_CHARS, "-")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module BlueConductor
|
2
|
+
module HTTP
|
3
|
+
module Song
|
4
|
+
class UrlGenerator
|
5
|
+
BASE_URI = "http://www.songlyrics.com/"
|
6
|
+
|
7
|
+
def self.generate(manager)
|
8
|
+
sanitizer = BlueConductor::HTTP::Song::Sanitizer.new(manager)
|
9
|
+
sanitizer.clean
|
10
|
+
|
11
|
+
"#{BASE_URI}#{sanitizer.band}/#{sanitizer.song}-lyrics/"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module BlueConductor
|
2
|
+
class Producer
|
3
|
+
attr_reader :band, :title, :songs, :image, :error
|
4
|
+
attr_accessor :url_generator, :request, :parser
|
5
|
+
|
6
|
+
def initialize(band, record_title)
|
7
|
+
@band = band
|
8
|
+
@title = record_title
|
9
|
+
@songs = nil
|
10
|
+
@image = ''
|
11
|
+
@error = ''
|
12
|
+
end
|
13
|
+
|
14
|
+
def record!
|
15
|
+
url = url_generator.generate(self)
|
16
|
+
html = request.fetch(url)
|
17
|
+
tracklist = parser.parse(html)
|
18
|
+
|
19
|
+
if tracklist.nil? || tracklist.empty?
|
20
|
+
@error = 'The album requested is not available || there was a spelling error'
|
21
|
+
else
|
22
|
+
@image = parser.parse_image(html)
|
23
|
+
|
24
|
+
@songs = tracklist.map do |song|
|
25
|
+
BlueConductor.song_for(@band, song)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
self
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/blue_conductor/song.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
module BlueConductor
|
2
2
|
class Song
|
3
|
-
attr_accessor :title, :band, :
|
3
|
+
attr_accessor :title, :band, :album, :lyrics
|
4
4
|
|
5
5
|
def initialize(manager)
|
6
6
|
@title = manager.song
|
7
7
|
@band = manager.band
|
8
|
+
@album = manager.album
|
8
9
|
@lyrics = manager.data
|
9
|
-
@error = manager.error
|
10
10
|
end
|
11
11
|
end
|
12
12
|
end
|
data/lyric
CHANGED
@@ -3,21 +3,20 @@ require 'spec_helper'
|
|
3
3
|
describe BlueConductor::BandManager do
|
4
4
|
subject { BlueConductor::BandManager.new(band, song) }
|
5
5
|
|
6
|
-
let(:band) { '
|
7
|
-
let(:song) { '
|
8
|
-
let(:data) { "
|
9
|
-
let(:
|
10
|
-
let(:song_object) { BlueConductor::Song.new(manager_mock) }
|
6
|
+
let(:band) { 'Van Halen' }
|
7
|
+
let(:song) { 'Unchained' }
|
8
|
+
let(:data) { "Change, nothin' stays the same" }
|
9
|
+
let(:album) { 'Fair Warning' }
|
11
10
|
|
12
11
|
before do
|
13
|
-
subject.url_generator = BlueConductor::HTTP::UrlGenerator
|
12
|
+
subject.url_generator = BlueConductor::HTTP::Song::UrlGenerator
|
14
13
|
subject.request = BlueConductor::HTTP::Request
|
15
|
-
subject.parser = BlueConductor::HTTP::Response
|
14
|
+
subject.parser = BlueConductor::HTTP::Song::Response
|
16
15
|
end
|
17
16
|
|
18
17
|
describe '.new' do
|
19
18
|
it 'creates an instance of itself' do
|
20
|
-
|
19
|
+
subject.band.should == band
|
21
20
|
subject.song.should == song
|
22
21
|
end
|
23
22
|
end
|
@@ -31,6 +30,7 @@ describe BlueConductor::BandManager do
|
|
31
30
|
|
32
31
|
@track.title.should == song
|
33
32
|
@track.band.should == band
|
33
|
+
@track.album.should == album
|
34
34
|
@track.lyrics.should =~ /#{data}/
|
35
35
|
end
|
36
36
|
end
|
@@ -44,7 +44,8 @@ describe BlueConductor::BandManager do
|
|
44
44
|
@track = subject.song!
|
45
45
|
end
|
46
46
|
|
47
|
-
@track.
|
47
|
+
@track.lyrics.should =~ /Sorry, we have no/
|
48
|
+
@track.album.should =~ /Album Missing/
|
48
49
|
@track.title.should == song
|
49
50
|
@track.band.should == band
|
50
51
|
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe BlueConductor::Producer do
|
4
|
+
subject { BlueConductor::Producer.new(band, record) }
|
5
|
+
|
6
|
+
let(:band) { 'Van Halen' }
|
7
|
+
let(:record) { 'Fair Warning' }
|
8
|
+
let(:track_list) { ['Dirty Movies', 'Hear About It Later', 'One Foot Out The Door',
|
9
|
+
'Push Comes to Shove', "Sinner's Swing", 'So This Is Love?',
|
10
|
+
'Sunday Afternoon In The Park', 'Unchained', 'Mean Street'
|
11
|
+
]}
|
12
|
+
|
13
|
+
before do
|
14
|
+
subject.url_generator = BlueConductor::HTTP::Record::UrlGenerator
|
15
|
+
subject.request = BlueConductor::HTTP::Request
|
16
|
+
subject.parser = BlueConductor::HTTP::Record::Response
|
17
|
+
end
|
18
|
+
|
19
|
+
describe '.new' do
|
20
|
+
it 'creates an instance of itself' do
|
21
|
+
subject.band.should == band
|
22
|
+
subject.title.should == record
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe '#record' do
|
27
|
+
context 'when the band and record are valid' do
|
28
|
+
it 'returns an array of songs' do
|
29
|
+
VCR.use_cassette 'full_album' do
|
30
|
+
@record = subject.record!
|
31
|
+
end
|
32
|
+
|
33
|
+
@record.songs.map(&:title).should == track_list
|
34
|
+
@record.image.should == 'http://cdn1.songlyricscom.netdna-cdn.com/album_covers/202/van-halen-fair-warning/van-halen-6832-fair-warning.jpg'
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'when the band and record are invalid' do
|
39
|
+
|
40
|
+
let(:band) { 'asdf' }
|
41
|
+
let(:record) { 'asdf'}
|
42
|
+
|
43
|
+
it 'raises an error' do
|
44
|
+
VCR.use_cassette 'invalid_album' do
|
45
|
+
@record = subject.record!
|
46
|
+
end
|
47
|
+
|
48
|
+
@record.error.should == 'The album requested is not available || there was a spelling error'
|
49
|
+
@record.band.should == band
|
50
|
+
@record.title.should == record
|
51
|
+
@record.songs.should == nil
|
52
|
+
@record.image.should == ''
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|