File Coverage

blib/lib/WWW/Yahoo/Movies.pm
Criterion Covered Total %
statement 63 202 31.1
branch 11 80 13.7
condition 5 29 17.2
subroutine 18 35 51.4
pod 6 11 54.5
total 103 357 28.8


line stmt bran cond sub pod time code
1             package WWW::Yahoo::Movies;
2              
3 5     5   140950 use strict;
  5         23  
  5         291  
4 5     5   39 use warnings;
  5         14  
  5         2279  
5              
6 5     5   46 use vars qw($VERSION $AUTOLOAD %FIELDS);
  5         9  
  5         584  
7              
8 5         45 use fields qw(
9             id
10             title
11             cover
12             year
13             mpaa_rating
14             distributor
15             release_date
16             runtime
17             genres
18             plot_summary
19             people
20             matched
21             error
22             error_msg
23             _proxy
24             _timeout
25             _user_agent
26             _page
27             _parser
28             _search
29             _server_url
30             _search_uri
31             _movie_uri
32 5     5   5383 );
  5         18118  
33              
34             BEGIN {
35 5     5   1241 $VERSION = '0.05';
36             }
37              
38 5     5   8908 use LWP::Simple qw(get $ua);
  5         615882  
  5         55  
39 5     5   6557 use HTML::TokeParser;
  5         345825  
  5         790  
40 5     5   45 use Carp;
  5         10  
  5         1221  
41              
42 5     5   12394 use Data::Dumper;
  5         46204  
  5         13566  
43              
44             {
45             my $_class_def = {
46             error => 0,
47             error_msg => '',
48             mpaa_rating => [],
49             _timeout => 10,
50             _user_agent => 'Mozilla/5.0',
51             _server_url => 'http://movies.yahoo.com',
52             _movie_uri => '/shop?d=hv&cf=info&id=',
53             _search_uri => '/mv/search?type=feature&p=',
54             };
55              
56 0     0   0 sub _class_def { $_class_def }
57             sub _get_default_val {
58 108     108   124 my $self = shift;
59 108         116 my $attr = shift;
60              
61 108         413 return $_class_def->{$attr};
62             }
63             }
64              
65              
66             sub new {
67 5     5 1 873 my $class = shift;
68 5         18 my $self = {};
69 5         17 bless $self, $class;
70 5         30 $self->_init(@_);
71 0         0 return $self;
72             }
73              
74             sub _init {
75 5     5   10 my $self = shift;
76 5         30 my %params = @_;
77            
78 5         56 for my $prop(keys %FIELDS) {
79 115         141 my $attr = $prop;
80 115         220 $attr =~ s/^_//;
81 115 100       319 $self->{$prop} = exists $params{$attr} ? $params{$attr}
82             : $self->_get_default_val($prop);
83             }
84            
85 5 50       34 if($self->proxy) { $ua->proxy(['http'], $self->proxy) }
  0         0  
86 5         52 else { $ua->env_proxy }
87              
88 5         9358 $ua->agent($self->user_agent);
89 5         692 $ua->timeout($self->timeout);
90            
91 5         115 $self->_get_page();
92 0 0       0 return if $self->error;
93              
94 0         0 $self->parse_page();
95             }
96              
97             sub _get_page {
98 5     5   11 my $self = shift;
99              
100 5 50 66     57 croak "Wrong paramter!" if $self->id !~ /^\d+$/ && $self->_search;
101            
102 5 100 66     75 my $url = $self->_server_url.($self->id =~ /^\d+$/ && length($self->id) > 4 ? $self->_movie_uri : $self->_search_uri).$self->id;
103              
104 5   50     228 $self->{_page} = get($url) || die "Cannot connect to the Yahoo: $!!";
105            
106 0 0 0     0 unless($self->id =~ /^\d+$/ && length($self->id) > 4) {
107 0         0 $self->_process_page();
108 0         0 $self->_search(1);
109             }
110             }
111              
112             sub _process_page {
113 0     0   0 my $self = shift;
114              
115 0 0       0 if($self->_page =~ /no\s+matches\s+were\s+found/i) {
116 0         0 $self->error_msg("Nothing found!");
117 0         0 $self->error(1);
118 0         0 return;
119             }
120              
121 0         0 my $parser = $self->_parser;
122            
123 0         0 my($tag, $text);
124 0         0 while($tag = $parser->get_tag('b')) {
125 0         0 $text = $parser->get_text();
126 0 0       0 last if $text =~ /top\s+matching\s+movie\s+titles/i;
127             }
128              
129 0         0 $parser->get_tag('table');
130            
131 0         0 while($tag = $parser->get_tag) {
132            
133 0 0 0     0 if($tag->[0] eq 'a' && $tag->[1]{href} =~ m#/(\d+)/info#) {
134 0         0 $text = $parser->get_trimmed_text('a', 'br');
135 0         0 my $id = $1;
136 0         0 $self->matched($id, $text);
137             }
138            
139 0 0       0 last if $tag->[0] eq '/table';
140             }
141              
142 0 0       0 if($self->matched) {
143 0         0 $self->id($self->matched->[0]{id});
144 0         0 $self->_get_page();
145             } else {
146 0         0 $self->error_msg("Nothing matched!");
147 0         0 $self->error(1);
148 0         0 return;
149             }
150             }
151              
152             sub matched {
153 0     0 1 0 my $self = shift;
154 0 0       0 if(@_) {
155 0         0 my($id, $title) = @_;
156 0         0 push @{ $self->{matched} }, {id => $id, title => $title};
  0         0  
157             }
158              
159 0         0 return $self->{matched};
160             }
161              
162             sub proxy {
163 5     5 0 12 my $self = shift;
164 5 50       25 if(@_) { $self->{_proxy} = shift }
  0         0  
165 5         23 return $self->{_proxy};
166             }
167              
168             sub timeout {
169 5     5 0 12 my $self = shift;
170 5 50       30 if(@_) { $self->{_timeout} = shift }
  0         0  
171 5         36 return $self->{_timeout}
172             }
173              
174             sub user_agent {
175 5     5 0 18 my $self = shift;
176 5 50       26 if(@_) { $self->{_user_agent} = shift }
  0         0  
177 5         43 return $self->{_user_agent}
178             }
179              
180             sub parse_page {
181 0     0 0 0 my $self = shift;
182              
183 0         0 $self->_parse_title();
184 0         0 $self->_parse_details();
185 0         0 $self->_parse_cover();
186 0         0 $self->_parse_trailer();
187 0         0 $self->_parse_plot();
188 0         0 $self->_parse_people();
189             }
190              
191             sub cover_file {
192 0     0 0 0 my $self = shift;
193 0 0       0 if($self->cover) {
194 0         0 my($file_name) = $self->cover =~ /(?:.+)\/(.+)$/;
195 0         0 return $file_name;
196             }
197             }
198              
199             sub mpaa_rating {
200 0     0 1 0 my $self = shift;
201            
202 0 0 0     0 if($_[0] && ref($_[0]) eq 'ARRAY') { $self->{mpaa_rating} = shift }
  0         0  
203            
204 0 0       0 return wantarray ? @{ $self->{mpaa_rating} } : $self->{mpaa_rating}[0];
  0         0  
205             }
206              
207             sub directors {
208 0     0 1 0 my $self = shift;
209              
210 0 0       0 return $self->{'people'}->{'directors'} if $self->{'people'};
211             }
212              
213             sub producers {
214 0     0 1 0 my $self = shift;
215              
216 0 0       0 return $self->{'people'}->{'producers'} if $self->{'people'};
217             }
218              
219             sub cast {
220 0     0 1 0 my $self = shift;
221              
222 0 0       0 return $self->{'people'}->{'cast'} if $self->{'people'};
223             }
224              
225             sub _parser {
226 0     0   0 my $self = shift;
227 0         0 $self->{_parser} = new HTML::TokeParser(\$self->_page());
228 0         0 return $self->{_parser};
229             }
230              
231             sub _parse_title {
232 0     0   0 my $self = shift;
233              
234 0         0 ($self->{title}, $self->{year}) =
235             $self->_page =~ m#

(.+)\s+\((\d+)\)

#mi;
236             }
237              
238             sub _parse_details {
239 0     0   0 my $self = shift;
240 0         0 my $p = $self->_parser();
241 0         0 while($p->get_tag('b')) {
242 0         0 my $t;
243 0         0 my $caption = $p->get_text;
244            
245 0         0 SWITCH: for($caption) {
246 0 0       0 /^Genres/ && do {
247 0         0 $t = $p->get_trimmed_text('/tr');
248 0         0 $self->genres([split m#/#, $t]);
249 0         0 last SWITCH; };
250 0 0       0 /^Running Time/ && do {
251 0         0 $t = $p->get_trimmed_text('/tr');
252 0         0 $self->runtime($self->_parse_runtime($t));
253 0         0 last SWITCH; };
254 0 0       0 /^Release Date/ && do {
255 0         0 $t = $p->get_trimmed_text('b');
256 0         0 my($mon, $day, $year) = $t =~ /(.+?)\s+(\d+)(?:th|sd|st)?,\s+(\d+)\s?(?:[.(])?/;
257 0         0 my $date = "$day $mon $year";
258 0         0 $self->release_date($date);
259 0         0 last SWITCH; };
260 0 0       0 /^MPAA Rating/ && do {
261 0         0 $t = $p->get_trimmed_text('/tr');
262 0         0 my($code, $descr) = $t =~ /(.+?)\s+(.+)/;
263 0         0 $self->mpaa_rating([$code, $descr]);
264 0         0 last SWITCH; };
265 0 0       0 /^Distributor/ && do {
266 0         0 $t = $p->get_trimmed_text('/tr');
267 0         0 my($distr) = $t =~ /(.*)\./;
268 0         0 $self->distributor($distr);
269 0         0 last SWITCH; };
270             };
271             }
272             }
273              
274             sub _parse_cover {
275 0     0   0 my $self = shift;
276 0         0 my $p = $self->_parser();
277            
278 0         0 while(my $tag = $p->get_tag('img')) {
279 0 0 0     0 if($tag->[1]{alt} && $tag->[1]{alt} =~ /^$self->{title}/i) {
280 0         0 $self->{cover} = $tag->[1]{src};
281 0         0 last;
282             }
283             }
284             }
285              
286             sub _parse_trailer {
287 0     0   0 my $self = shift;
288 0         0 my $p = $self->_parser();
289              
290 0         0 while(my $tag = $p->get_tag('a')) {
291 0 0       0 if($tag->[1]{href} =~ /videoWin/i) {
292 0         0 $self->{trailer} = $tag->[1]{href};
293 0         0 last;
294             }
295             }
296             }
297              
298             sub _parse_plot {
299 0     0   0 my $self = shift;
300 0         0 my $p = $self->_parser();
301              
302 0         0 while(my $tag = $p->get_token()) {
303 0 0       0 if($tag->[0] eq 'C') {
304 0 0       0 last if $tag->[1] =~ /another vertical spacer/;
305             }
306             }
307              
308 0         0 $p->get_tag('font');
309 0         0 $self->{plot_summary} = $p->get_trimmed_text('font', 'table');
310             }
311              
312             sub _parse_runtime {
313 0     0   0 my($self, $time_str) = @_;
314 0         0 my $time = '';
315            
316 0 0       0 if($time_str) {
317 0         0 my($hours, $min) =
318             $time_str =~ m#(\d{0,2})(?:\s+hr\w?\.?)(?:\s+?)(\d{1,2})\s+min\.?#;
319 0         0 $time = $hours*60 + $min;
320             }
321              
322 0         0 return $time;
323             }
324              
325             sub _parse_people {
326 0     0   0 my($self) = @_;
327            
328 0         0 my $p = $self->_parser();
329            
330 0         0 my $key;
331 0         0 while(my $tag = $p->get_token()) {
332 0 0 0     0 last if $tag->[0] eq 'C' && $tag->[1] =~ /cast and credits/;
333             }
334              
335 0         0 while(my $tag = $p->get_token) {
336            
337 0 0       0 if($tag->[1] eq 'font') {
338 0         0 my $text = $p->get_text();
339              
340 0 0       0 if($text eq 'Starring:') { $key = 'cast' }
  0 0       0  
    0          
341 0         0 elsif($text eq 'Directed by:') { $key = 'directors' }
342 0         0 elsif($text eq 'Produced by:') { $key = 'producers' }
343             }
344              
345 0 0 0     0 if($tag->[0] eq 'S' && $tag->[1] eq 'a') {
346 0 0 0     0 if($tag->[2]{href} =~ /movie\/contributor\/(\d+)/ && $key) {
347 0         0 push @{ $self->{'people'}->{$key} }, [$1, $p->get_text];
  0         0  
348             }
349             }
350             }
351             }
352              
353             sub AUTOLOAD {
354 30     30   44 my $self = shift;
355 30         252 my($class, $attr) = $AUTOLOAD =~ /(.*)::(.*)/;
356 30         104 my($pack, $file, $line) = caller;
357 30 50       77 if(exists $FIELDS{$attr}) {
358 30 50       66 $self->{$attr} = shift() if @_;
359 30         340 return $self->{$attr};
360             } else {
361 0         0 carp "Method [$attr] not found in the class [$class]!\n Called from $pack at line $line";
362             }
363             }
364              
365             sub DESTROY {
366 5     5   2059680 my $self = shift;
367             }
368              
369             1;
370             __END__