File Coverage

blib/lib/WWW/Scraper/ISBN/OpenLibrary_Driver.pm
Criterion Covered Total %
statement 63 79 79.7
branch 9 24 37.5
condition 12 24 50.0
subroutine 11 11 100.0
pod 1 1 100.0
total 96 139 69.0


\s*\s*
line stmt bran cond sub pod time code
1             package WWW::Scraper::ISBN::OpenLibrary_Driver;
2              
3 6     6   131145 use strict;
  6         16  
  6         264  
4 6     6   32 use warnings;
  6         11  
  6         251  
5              
6 6     6   34 use vars qw($VERSION @ISA);
  6         14  
  6         581  
7             $VERSION = '0.09';
8              
9             #--------------------------------------------------------------------------
10              
11             =head1 NAME
12              
13             WWW::Scraper::ISBN::OpenLibrary_Driver - Search driver for OpenLibrary online book catalog.
14              
15             =head1 SYNOPSIS
16              
17             See parent class documentation (L)
18              
19             =head1 DESCRIPTION
20              
21             Searches for book information from OpenLibrary online book catalog
22              
23             =cut
24              
25             #--------------------------------------------------------------------------
26              
27             ###########################################################################
28             # Inheritence
29              
30 6     6   36 use base qw(WWW::Scraper::ISBN::Driver);
  6         9  
  6         3824  
31              
32             ###########################################################################
33             # Modules
34              
35 6     6   13098 use WWW::Mechanize;
  6         899546  
  6         309  
36 6     6   3719 use JSON;
  6         48810  
  6         47  
37              
38             ###########################################################################
39             # Constants
40              
41 6     6   1088 use constant SEARCH => 'http://openlibrary.org/api/books?jscmd=data&format=json&bibkeys=ISBN:';
  6         9  
  6         371  
42 6     6   32 use constant LB2G => 453.59237; # number of grams in a pound (lb)
  6         9  
  6         294  
43 6     6   31 use constant OZ2G => 28.3495231; # number of grams in an ounce (oz)
  6         11  
  6         272  
44 6     6   56 use constant IN2MM => 25.4; # number of inches in a millimetre (mm)
  6         10  
  6         6010  
45              
46             #--------------------------------------------------------------------------
47              
48             ###########################################################################
49             # Public Interface
50              
51             =head1 METHODS
52              
53             =over 4
54              
55             =item C
56              
57             Creates a query string, then passes the appropriate form fields to the OpenLibrary
58             server.
59              
60             The returned page should be the correct catalog page for that ISBN. If not the
61             function returns zero and allows the next driver in the chain to have a go. If
62             a valid page is returned, the following fields are returned via the book hash:
63              
64             isbn (now returns isbn13)
65             isbn10
66             isbn13
67             ean13 (industry name)
68             author
69             title
70             book_link
71             image_link
72             pubdate
73             publisher
74             binding (if known)
75             pages (if known)
76             weight (if known) (in grammes)
77             width (if known) (in millimetres)
78             height (if known) (in millimetres)
79             depth (if known) (in millimetres)
80              
81             The book_link and image_link refer back to the OpenLibrary website.
82              
83             =back
84              
85             =cut
86              
87             sub search {
88 4     4 1 11540 my $self = shift;
89 4         10 my $isbn = shift;
90 4         8 my $data;
91 4         18 $self->found(0);
92 4         77 $self->book(undef);
93              
94 4         64 my $mech = WWW::Mechanize->new();
95 4         14378 $mech->agent_alias( 'Linux Mozilla' );
96              
97 4         354 eval { $mech->get( SEARCH . $isbn ) };
  4         27  
98 4 50 33     14882710 return $self->handler("OpenLibrary website appears to be unavailable.")
      33        
99             if($@ || !$mech->success() || !$mech->content());
100              
101 4         429 my $code = decode_json($mech->content());
102             #use Data::Dumper;
103             #print STDERR "\n# code=".Dumper($code);
104              
105 4 100       241 return $self->handler("Failed to find that book on OpenLibrary website.")
106             unless($code->{'ISBN:'.$isbn});
107              
108 3         18 $data->{isbn13} = $code->{'ISBN:'.$isbn}{identifiers}{isbn_13}[0];
109 3         14 $data->{isbn10} = $code->{'ISBN:'.$isbn}{identifiers}{isbn_10}[0];
110              
111 3 50 66     21 return $self->handler("Failed to find that book on OpenLibrary website.")
112             unless($isbn eq $data->{isbn13} || $isbn eq $data->{isbn10});
113              
114             #use Data::Dumper;
115             #print STDERR "\n# " . Dumper($data);
116              
117 3         12 $data->{isbn13} = $code->{'ISBN:'.$isbn}{identifiers}{isbn_13}[0];
118 3         10 $data->{isbn10} = $code->{'ISBN:'.$isbn}{identifiers}{isbn_10}[0];
119 3         11 $data->{image} = $code->{'ISBN:'.$isbn}{cover}{large};
120 3         11 $data->{thumb} = $code->{'ISBN:'.$isbn}{cover}{small};
121 3         12 $data->{author} = $code->{'ISBN:'.$isbn}{authors}[0]{name};
122 3         12 $data->{title} = $code->{'ISBN:'.$isbn}{title};
123 3         9 $data->{publisher} = $code->{'ISBN:'.$isbn}{publishers}[0]{name};
124 3         10 $data->{pubdate} = $code->{'ISBN:'.$isbn}{publish_date};
125 3         8 $data->{pages} = $code->{'ISBN:'.$isbn}{number_of_pages};
126 3         10 $data->{url} = $code->{'ISBN:'.$isbn}{url};
127 3         23 $data->{weight} = $code->{'ISBN:'.$isbn}{weight};
128              
129 3 100 100     57 if($data->{weight}&& $data->{weight} =~ /([\d.]+)\s*(?:lbs|pounds)/) {
    100 66        
    50 33        
130 1         264 $data->{weight} = int($1 * LB2G);
131             } elsif($data->{weight} && $data->{weight} =~ /([\d.]+)\s*(?:ozs|ounces)/) {
132 1         7 $data->{weight} = int($1 * OZ2G);
133             } elsif($data->{weight} && $data->{weight} =~ /([\d.]+)\s*(?:g|grams)/) {
134 0         0 $data->{weight} = int($1);
135             } else {
136 1         2 $data->{weight} = undef;
137             }
138              
139 3         11 eval { $mech->get( $data->{url} ) };
  3         20  
140 3 0 33     943597 return $self->handler("OpenLibrary website appears to be unavailable.")
      33        
141             if($@ || !$mech->success() || !$mech->content());
142              
143             # The Book page
144 0           my $html = $mech->content();
145             #print STDERR "\n# html=[\n$html\n]\n";
146              
147             # catch any data not in the JSON
148 0           ($data->{height},$data->{width},$data->{depth})
149             = $html =~ m!Dimensions([\d.]+)\s+x\s+([\d.]+)\s+x\s+([\d.]+)\s+inches!i;
150 0           ($data->{binding}) = $html =~ m!Format([^<]+)!i;
151              
152 0 0         $data->{height} = int($data->{height} * IN2MM) if($data->{height});
153 0 0         $data->{width} = int($data->{width} * IN2MM) if($data->{width});
154 0 0         $data->{depth} = int($data->{depth} * IN2MM) if($data->{depth});
155              
156             #use Data::Dumper;
157             #print STDERR "\n# " . Dumper($data);
158              
159 0 0         return $self->handler("Could not extract data from OpenLibrary result page.")
160             unless(defined $data);
161              
162             # trim top and tail
163 0 0         foreach (keys %$data) { next unless(defined $data->{$_});$data->{$_} =~ s/^\s+//;$data->{$_} =~ s/\s+$//; }
  0            
  0            
  0            
164              
165 0           my $bk = {
166             'ean13' => $data->{isbn13},
167             'isbn13' => $data->{isbn13},
168             'isbn10' => $data->{isbn10},
169             'isbn' => $data->{isbn13},
170             'author' => $data->{author},
171             'title' => $data->{title},
172             'book_link' => $mech->uri(),
173             'image_link' => $data->{image},
174             'thumb_link' => $data->{thumb},
175             'pubdate' => $data->{pubdate},
176             'publisher' => $data->{publisher},
177             'binding' => $data->{binding},
178             'pages' => $data->{pages},
179             'weight' => $data->{weight},
180             'width' => $data->{width},
181             'height' => $data->{height},
182             'depth' => $data->{depth},
183             'json' => $code,
184             'html' => $html
185             };
186              
187             #use Data::Dumper;
188             #print STDERR "\n# book=".Dumper($bk);
189              
190 0           $self->book($bk);
191 0           $self->found(1);
192 0           return $self->book;
193             }
194              
195             1;
196             __END__