File Coverage

blib/lib/WWW/Scraper/ISBN/TheNile_Driver.pm
Criterion Covered Total %
statement 60 60 100.0
branch 10 18 55.5
condition 8 18 44.4
subroutine 7 7 100.0
pod 1 1 100.0
total 86 104 82.6


line stmt bran cond sub pod time code
1             package WWW::Scraper::ISBN::TheNile_Driver;
2              
3 6     6   118381 use strict;
  6         20  
  6         267  
4 6     6   29 use warnings;
  6         9  
  6         1285  
5              
6 6     6   33 use vars qw($VERSION @ISA);
  6         11  
  6         560  
7             $VERSION = '0.14';
8              
9             #--------------------------------------------------------------------------
10              
11             =head1 NAME
12              
13             WWW::Scraper::ISBN::TheNile_Driver - Search driver for TheNile 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 TheNile 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         10  
  6         3570  
31              
32             ###########################################################################
33             # Modules
34              
35 6     6   10568 use WWW::Mechanize;
  6         914435  
  6         303  
36              
37             ###########################################################################
38             # Constants
39              
40 6     6   65 use constant SEARCH => 'http://www.thenile.com.au/search.php?s=';
  6         9  
  6         6017  
41              
42             #--------------------------------------------------------------------------
43              
44             ###########################################################################
45             # Public Interface
46              
47             =head1 METHODS
48              
49             =over 4
50              
51             =item C
52              
53             Creates a query string, then passes the appropriate form fields to the
54             TheNile server.
55              
56             The returned page should be the correct catalog page for that ISBN. If not the
57             function returns zero and allows the next driver in the chain to have a go. If
58             a valid page is returned, the following fields are returned via the book hash:
59              
60             isbn (now returns isbn13)
61             isbn10
62             isbn13
63             ean13 (industry name)
64             author
65             title
66             book_link
67             image_link
68             description
69             pubdate
70             publisher
71             binding (if known)
72             pages (if known)
73             weight (if known) (in grammes)
74             width (if known) (in millimetres)
75             height (if known) (in millimetres)
76              
77             The book_link and image_link refer back to the TheNile website.
78              
79             =back
80              
81             =cut
82              
83             sub search {
84 4     4 1 25872 my $self = shift;
85 4         8 my $isbn = shift;
86 4         14 $self->found(0);
87 4         48 $self->book(undef);
88              
89             # validate and convert into EAN13 format
90 4         36 my $ean = $self->convert_to_ean13($isbn);
91 4 50 66     190 return $self->handler("Invalid ISBN specified [$isbn]")
      33        
      66        
      33        
92             if(!$ean || (length $isbn == 13 && $isbn ne $ean)
93             || (length $isbn == 10 && $isbn ne $self->convert_to_isbn10($ean)));
94 4         33 $isbn = $ean;
95              
96 4         31 my $mech = WWW::Mechanize->new();
97 4         22155 $mech->agent_alias( 'Linux Mozilla' );
98              
99 4         251 eval { $mech->get( SEARCH . $isbn ) };
  4         22  
100 4 50 33     3199073 return $self->handler("TheNile website appears to be unavailable.")
      33        
101             if($@ || !$mech->success() || !$mech->content());
102              
103             # The Book page
104 4         272 my $html = $mech->content();
105              
106 4 50       3925 return $self->handler("Failed to find that book on TheNile website.")
107             if($html =~ m!Sorry your search.*?did not return any results|This book is currently unavailable!si);
108            
109             #print STDERR "\n# html=[\n$html\n]\n";
110              
111 4         9 my $data;
112 4         198 ($data->{image}) = $html =~ m!(http://c\d+\.mrcdn\.net/[\w\.\/]+\.jpg)!si;
113 4         169 ($data->{thumb}) = $html =~ m!(http://c\d+\.mrcdn\.net/[\w\.\/]+\.jpg)!si;
114 4         2703 ($data->{isbn13},$data->{isbn10}) = $html =~ m!
  • ISBN\s*]+>\s*(\d+)\s*/\s*(\d+)\s*
  • !si;
    115 4         2394 ($data->{author}) = $html =~ m!
  • Authors?\s*((?:]+>[^<]+(?:\s*(?:and|,)\s*)?)+)
  • !si;
    116 4 50       19 ($data->{author}) = $html =~ m!
  • Authors?\s*([^<]+)
  • !si unless($data->{author});
    117 4         1336 ($data->{title}) = $html =~ m!
  • Title\s*([^,<]+)
  • !si;
    118 4         3242 ($data->{publisher}) = $html =~ m!
  • Publisher\s*]+>\s*]+>\s*([^<]+)
  • !si;
    119 4 50       19 ($data->{publisher}) = $html =~ m!
  • Publisher\s*([^<]+)
  • !si unless($data->{publisher});
    120 4         1506 ($data->{pubdate}) = $html =~ m!
  • Year\s*([^<]+)
  • !si;
    121 4         3085 ($data->{binding}) = $html =~ m!
  • Format\s*]+>\s*([^<]+)
  • !si;
    122 4         1410 ($data->{pages}) = $html =~ m!
  • Pages\s*([\d.]+)
  • !si;
    123 4         3305 ($data->{weight}) = $html =~ m!
  • Weight\s*(\d+)g
  • !si;
    124 4         1518 ($data->{width},$data->{height}) = $html =~ m!
  • Dimensions\s*([\d.]+)mm x ([\d.]+)mm(?: x [\d.]+mm)?
  • !si;
    125 4         1595 ($data->{description}) = $html =~ m!

    Annotation

    \s*\s*
    (.*?)
    !si;
    126 4 50       20 ($data->{description}) = $html =~ m!

    Publisher Description

    \s*\s*
    (.*?)
    !si unless($data->{description});
    127            
    128 4         15 for(qw(author publisher description)) {
    129 12 50       123 $data->{$_} =~ s!<[^>]+>!!g if($data->{$_});
    130             }
    131              
    132             #use Data::Dumper;
    133             #print STDERR "\n# " . Dumper($data);
    134              
    135 4 50       15 return $self->handler("Could not extract data from TheNile result page.")
    136             unless(defined $data);
    137              
    138             # trim top and tail
    139 4 100       30 foreach (keys %$data) { next unless(defined $data->{$_});$data->{$_} =~ s/^\s+//;$data->{$_} =~ s/\s+$//; }
      56         96  
      52         93  
      52         146  
    140              
    141 4         37 my $url = $mech->uri();
    142              
    143 4         164 my $bk = {
    144             'ean13' => $data->{isbn13},
    145             'isbn13' => $data->{isbn13},
    146             'isbn10' => $data->{isbn10},
    147             'isbn' => $data->{isbn13},
    148             'author' => $data->{author},
    149             'title' => $data->{title},
    150             'book_link' => "$url",
    151             'image_link' => $data->{image},
    152             'thumb_link' => $data->{thumb},
    153             'description' => $data->{description},
    154             'pubdate' => $data->{pubdate},
    155             'publisher' => $data->{publisher},
    156             'binding' => $data->{binding},
    157             'pages' => $data->{pages},
    158             'weight' => $data->{weight},
    159             'width' => $data->{width},
    160             'height' => $data->{height},
    161             'depth' => $data->{depth},
    162             'html' => $html
    163             };
    164              
    165             #use Data::Dumper;
    166             #print STDERR "\n# book=".Dumper($bk);
    167              
    168 4         130 $self->book($bk);
    169 4         61 $self->found(1);
    170 4         38 return $self->book;
    171             }
    172              
    173             1;
    174              
    175             __END__