File Coverage

blib/lib/WWW/Scraper/ISBN/BarnesNoble_Driver.pm
Criterion Covered Total %
statement 81 81 100.0
branch 12 22 54.5
condition 6 18 33.3
subroutine 10 10 100.0
pod 1 1 100.0
total 110 132 83.3


line stmt bran cond sub pod time code
1             package WWW::Scraper::ISBN::BarnesNoble_Driver;
2              
3 7     7   106474 use strict;
  7         16  
  7         240  
4 7     7   32 use warnings;
  7         11  
  7         213  
5              
6 7     7   26 use vars qw($VERSION @ISA);
  7         10  
  7         520  
7             $VERSION = '0.21';
8              
9             #--------------------------------------------------------------------------
10              
11             =head1 NAME
12              
13             WWW::Scraper::ISBN::BarnesNoble_Driver - Search driver for the Barnes and Noble 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 the Barnes and Noble online book catalog
22              
23             =cut
24              
25             #--------------------------------------------------------------------------
26              
27             ###########################################################################
28             # Inheritence
29              
30 7     7   28 use base qw(WWW::Scraper::ISBN::Driver);
  7         9  
  7         3242  
31              
32             ###########################################################################
33             # Modules
34              
35 7     7   10088 use WWW::Mechanize;
  7         825385  
  7         337  
36              
37             ###########################################################################
38             # Constants
39              
40 7     7   62 use constant REFERER => 'http://www.barnesandnoble.com/';
  7         11  
  7         478  
41 7     7   27 use constant SEARCH => 'http://www.barnesandnoble.com/include/quicksearch_newSearch.asp?page=index&prod=univ&choice=allproducts&query=%s&flag=False&ATL_lid=hu0MIVVMgy&ATL_userid=hu0MIVVMgy&ATL_sid=v24Vd2sM16&ATL_seqnum=5';
  7         10  
  7         286  
42 7     7   30 use constant IN2MM => 25.4; # number of inches in a millimetre (mm)
  7         9  
  7         7204  
43              
44             #--------------------------------------------------------------------------
45              
46             ###########################################################################
47             # Public Interface
48              
49             =head1 METHODS
50              
51             =over 4
52              
53             =item C
54              
55             Creates a query string, then passes the appropriate form fields to the
56             Barnes and Noble server.
57              
58             The returned page should be the correct catalog page for that ISBN. If not the
59             function returns zero and allows the next driver in the chain to have a go. If
60             a valid page is returned, the following fields are returned via the book hash:
61              
62             isbn (now returns isbn13)
63             isbn10
64             isbn13
65             ean13 (industry name)
66             author
67             title
68             book_link
69             image_link
70             description
71             pubdate
72             publisher
73             binding (if known)
74             pages (if known)
75             weight (if known) (in grammes)
76             width (if known) (in millimetres)
77             height (if known) (in millimetres)
78             depth (if known) (in millimetres)
79              
80             The book_link and image_link refer back to the Barnes and Noble website.
81              
82             =back
83              
84             =cut
85              
86             sub search {
87 2     2 1 10334 my $self = shift;
88 2         4 my $isbn = shift;
89 2         14 $self->found(0);
90 2         48 $self->book(undef);
91              
92             # validate and convert into EAN13 format
93 2         25 my $ean = $self->convert_to_ean13($isbn);
94 2 50 33     106 return $self->handler("Invalid ISBN specified [$isbn]")
      33        
      33        
      33        
95             if(!$ean || (length $isbn == 13 && $isbn ne $ean)
96             || (length $isbn == 10 && $isbn ne $self->convert_to_isbn10($ean)));
97              
98 2         14 my $mech = WWW::Mechanize->new();
99 2         11930 $mech->agent_alias( 'Linux Mozilla' );
100 2         118 $mech->add_header( 'Accept-Encoding' => undef );
101 2         21 $mech->add_header( 'Referer' => REFERER );
102              
103 2         19 my $url = sprintf SEARCH, $ean, $ean;
104             #print STDERR "\n# ean=$ean, link=[$url]\n";
105              
106 2         4 eval { $mech->get( $url ) };
  2         8  
107 2 50 33     1922683 return $self->handler("the Barnes and Noble website appears to be unavailable. [$@]")
      33        
108             if($@ || !$mech->success() || !$mech->content());
109              
110             # The Book page
111 2         107 my $html = $mech->content();
112              
113 2 50   1   4913 return $self->handler("Failed to find that book on the Barnes and Noble website. [$isbn]")
  1         11  
  1         3  
  1         39  
114             if($html =~ m!Sorry. We did not find any results|Sorry, we could not find what you were looking for!si);
115            
116 2         25904 $html =~ s/&/&/g;
117 2         1144 $html =~ s/�?39;/'/g;
118 2         1080 $html =~ s/ / /g;
119             #print STDERR "\n# html=[\n$html\n]\n";
120              
121 2         5 my $data;
122 2         25 ($data->{isbn10}) = $self->convert_to_isbn10($ean);
123 2         3113 ($data->{isbn13}) = $html =~ m!ISBN-13:\s*(\d+)!si;
124 2         3129 ($data->{publisher}) = $html =~ m!Publisher: \s*([^<]+)\s*!si;
125 2         3000 ($data->{pubdate}) = $html =~ m!Publication date: \s*([^<]+)\s*!si;
126 2         240 ($data->{title}) = $html =~ m!]*>!si;
127 2         1539 ($data->{author}) = $html =~ m!
    (.*?)
!si;
128 2         4341 ($data->{pages}) = $html =~ m!Pages: \s*(.*?)\s*!si;
129 2         121 ($data->{binding}) = $html =~ m![^\|]+\|[^\|]+\|\s*(.*?)\s*\|[^<]+!si;
130 2         258 ($data->{image}) = $html =~ m!]*>!si;
131 2         255 ($data->{thumb}) = $html =~ m!]*>!si;
132 2         1967 ($data->{description}) = $html =~ m!product-commentary-overview-1.*?

Overview

\s*(.*?)\s*\s*!si;
133 2         3278 ($data->{width},$data->{height},$data->{depth})
134             = $html =~ m!Product dimensions:\s*([\d.]+)\s*\(w\)\s*x\s*([\d.]+)\s*\(h\)\s*x\s*([\d.]+)\s*\(d\)!si;
135              
136             # currently not provided
137 2         81 ($data->{weight}) = $html =~ m!Weight:\s*([^<]+)!s;
138              
139 2 50       22 $data->{depth} = int($data->{depth} * IN2MM) if($data->{depth});
140 2 50       9 $data->{width} = int($data->{width} * IN2MM) if($data->{width});
141 2 50       7 $data->{height} = int($data->{height} * IN2MM) if($data->{height});
142 2 50       5 $data->{weight} = int($data->{weight}) if($data->{weight});
143              
144 2         6 for(qw(author publisher description)) {
145 6 50       15 next unless($data->{$_});
146 6         180 $data->{$_} =~ s![ \t\n\r]+! !g;
147 6         75 $data->{$_} =~ s!<[^>]+>!!g;
148             }
149              
150 2 50       8 if($data->{author}) {
151 2         12 $data->{author} =~ s!^\s*by\s*!!;
152 2         15 $data->{author} =~ s!,\s*!, !g;
153             }
154              
155             #use Data::Dumper;
156             #print STDERR "\n# data=" . Dumper($data);
157              
158 2 50       8 return $self->handler("Could not extract data from the Barnes and Noble result page.")
159             unless(defined $data);
160              
161             # trim top and tail
162 2         14 foreach (keys %$data) {
163 30 100       57 next unless(defined $data->{$_});
164 27         46 $data->{$_} =~ s/^\s+//;
165 27         80 $data->{$_} =~ s/\s+$//;
166             }
167              
168 2         17 $url = $mech->uri();
169              
170 2         97 my $bk = {
171             'ean13' => $data->{isbn13},
172             'isbn13' => $data->{isbn13},
173             'isbn10' => $data->{isbn10},
174             'isbn' => $data->{isbn13},
175             'author' => $data->{author},
176             'title' => $data->{title},
177             'book_link' => $url,
178             'image_link' => $data->{image},
179             'thumb_link' => $data->{thumb},
180             'description' => $data->{description},
181             'pubdate' => $data->{pubdate},
182             'publisher' => $data->{publisher},
183             'binding' => $data->{binding},
184             'pages' => $data->{pages},
185             'weight' => $data->{weight},
186             'width' => $data->{width},
187             'height' => $data->{height},
188             'depth' => $data->{depth},
189             'html' => $html
190             };
191              
192             #use Data::Dumper;
193             #print STDERR "\n# book=".Dumper($bk);
194              
195 2         8 $self->book($bk);
196 2         38 $self->found(1);
197 2         15 return $self->book;
198             }
199              
200             1;
201              
202             __END__