File Coverage

blib/lib/WebService/SongLyrics.pm
Criterion Covered Total %
statement 20 57 35.0
branch 0 16 0.0
condition 0 3 0.0
subroutine 6 11 54.5
pod 2 2 100.0
total 28 89 31.4


line stmt bran cond sub pod time code
1             =head1 NAME
2              
3             WebService::SongLyrics - Retrieve song lyrics from www.songlyrics.com
4              
5             =head1 SYNOPSIS
6              
7             use WebService::SongLyrics;
8              
9             my $wsl = WebService::SongLyrics->new;
10              
11             my $lyrics = $wsl->get_lyrics("Beyonce", "Crazy in love");
12              
13             =head1 DESCRIPTION
14              
15             The WebService::SongLyrics module attempts to scrape song lyrics from
16             http://www.songlyrics.com Due to the nature of screen scraping it's not
17             the most resilient of code.
18              
19             Thanks to the sites search engine it's a little picky about the
20             phrasing of the song and artist. It especially doesn't like "Artist ft
21             other artist".
22              
23             =head1 EXAMPLES
24              
25             use WebService::SongLyrics;
26              
27             my $wsl = WebService::SongLyrics->new;
28              
29             my $lyrics = $wsl->get_lyrics("Beyonce", "Crazy in love");
30              
31             print $lyrics, "\n" if $lyrics;
32              
33             =cut
34              
35             #######################################################################
36              
37             package WebService::SongLyrics;
38 1     1   25093 use strict;
  1         3  
  1         43  
39 1     1   6 use warnings;
  1         2  
  1         34  
40 1     1   1187 use LWP::UserAgent;
  1         63766  
  1         34  
41 1     1   11 use URI::Escape;
  1         1  
  1         80  
42 1     1   5 use vars qw($VERSION);
  1         2  
  1         722  
43              
44             $VERSION = '0.01';
45             my $ua = new LWP::UserAgent;
46              
47             =head1 METHODS
48              
49             =over 4
50              
51             =item new ( chart => 'chart type' )
52              
53             This is the constructor for a new WebService::SongLyrics object. It takes
54             no arguments and simply returns a new instance.
55              
56             =back
57              
58             =cut
59              
60             sub new {
61 1     1 1 12 my $class = shift;
62 1         3 my $self = {};
63              
64 1         4 $self->{base_url} = 'http://www.songlyrics.com';
65              
66 1         5 bless ($self, $class);
67 1         3 return $self;
68             }
69              
70             #----------------------------------------#
71              
72             =over 4
73              
74             =item get_lyrics ( $artist, $song_title )
75              
76             The C method requires both an artist and a song title and
77             returns the lyrics for the given combination. If it can find them.
78              
79             It returns C if you fail to pass in either parameter or if it
80             can't find the lyrics. It Cs with a short message and the URL if
81             the server can't be found or it gets a HTTP status code that
82             indicates failure.
83              
84             =back
85              
86             =cut
87              
88              
89             sub get_lyrics {
90 0     0 1   my $self = shift;
91 0           my ($artist, $song_title) = @_;
92              
93 0 0 0       return unless ($artist && $song_title);
94              
95 0           my $artist_url = _get_pages($artist, $song_title, $self->{base_url});
96 0           my $lyrics_page = _get_lyrics_page($artist_url, $song_title, $self->{base_url});
97 0           my $lyrics = _get_lyrics($lyrics_page);
98              
99 0           return $lyrics;
100             }
101              
102             #----------------------------------------#
103              
104             sub _get {
105 0     0     my $url = shift;
106 0           my $resource = $ua->get($url);
107              
108 0 0         if ( $resource->is_success ) {
109 0           return $resource->content;
110             } else {
111 0           die "Failed to process '$url'";
112             }
113             }
114              
115             #----------------------------------------#
116              
117             # get the results from the search and try and pull out the right page
118              
119             sub _get_pages {
120 0     0     my $artist = shift;
121 0           my $songtitle = shift;
122 0           my $base_url = shift;
123 0           my @matches;
124              
125 0           my $search = uri_escape("$artist $songtitle");
126 0           my $cruft = qq!/search.php?key=$search&x=13&y=8&sb%5B0%5D=_author&sb%5B2%5D=_name!;
127              
128 0           my $content = _get("$base_url$cruft");
129              
130 0 0         if ($content) {
131 0 0         if ($content =~ m!
132 0           return $1;
133             }
134             }
135             }
136              
137             #----------------------------------------#
138              
139             # find the now we've got the search results find the link that matches the
140             # song title and pull it out.
141              
142             sub _get_lyrics_page {
143 0     0     my $lyrics_path = shift;
144 0           my $song_title = shift;
145 0           my $base_url = shift;
146 0           my $lyrics_url = "$base_url$lyrics_path";
147              
148 0           my $content = _get($lyrics_url);
149              
150 0 0         if ($content) {
151 0 0         if ($content =~ m!$song_title!i) {
152 0           return "$base_url$1";
153             }
154             }
155             }
156              
157             #----------------------------------------#
158              
159             # get the page with the lyrics and extract them with a very fragile regex
160              
161             sub _get_lyrics {
162 0     0     my $lyrics_page = shift;
163              
164 0           my $content = _get($lyrics_page);
165              
166 0 0         if ($content) { # this regex is very fragile.
167 0 0         if ($content =~ m!Ringtones(.*?)
!s) {
168 0           my $lyrics = $1;
169 0           $lyrics =~ s/
//g;
170 0           return $lyrics;
171             }
172             }
173             }
174             #----------------------------------------#
175              
176             1;
177              
178             #######################################################################
179              
180             =head1 NOTES
181              
182             I originally planned to release this under the Lyrics::Fetch namespace but
183             after spending some time digging through the (very limited) docs and
184             descriptions I thought it'd be better to do it as a stand-alone module.
185              
186             The namespace is a little pretentious but it does fit with the other
187             WebService::DomainName modules already on CPAN.
188              
189             =head1 DEPENDENCIES
190              
191             WebService::SongLyrics requires the following modules:
192              
193             L
194              
195             L
196              
197             =head1 LICENCE AND COPYRIGHT
198              
199             Copyright (C) 2006 Dean Wilson. All Rights Reserved.
200              
201             This module is free software; you can redistribute it and/or modify it
202             under the same terms as Perl itself.
203              
204             =head1 AUTHOR
205              
206             Dean Wilson
207              
208             =cut