line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package WWW::Scraper::ISBN::GoogleBooks_Driver; |
2
|
|
|
|
|
|
|
|
3
|
5
|
|
|
5
|
|
284978
|
use strict; |
|
5
|
|
|
|
|
37
|
|
|
5
|
|
|
|
|
147
|
|
4
|
5
|
|
|
5
|
|
31
|
use warnings; |
|
5
|
|
|
|
|
11
|
|
|
5
|
|
|
|
|
170
|
|
5
|
5
|
|
|
5
|
|
2876
|
use utf8; |
|
5
|
|
|
|
|
73
|
|
|
5
|
|
|
|
|
28
|
|
6
|
|
|
|
|
|
|
|
7
|
5
|
|
|
5
|
|
196
|
use vars qw($VERSION @ISA); |
|
5
|
|
|
|
|
10
|
|
|
5
|
|
|
|
|
415
|
|
8
|
|
|
|
|
|
|
$VERSION = '0.31'; |
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
=head1 NAME |
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
WWW::Scraper::ISBN::GoogleBooks_Driver - Search driver for Google Books online book catalog. |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
=head1 SYNOPSIS |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
See parent class documentation (L) |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
=head1 DESCRIPTION |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
Searches for book information from Google Books online book catalog |
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
=cut |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
########################################################################### |
29
|
|
|
|
|
|
|
# Inheritence |
30
|
|
|
|
|
|
|
|
31
|
5
|
|
|
5
|
|
31
|
use base qw(WWW::Scraper::ISBN::Driver); |
|
5
|
|
|
|
|
12
|
|
|
5
|
|
|
|
|
2543
|
|
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
########################################################################### |
34
|
|
|
|
|
|
|
# Modules |
35
|
|
|
|
|
|
|
|
36
|
5
|
|
|
5
|
|
7999
|
use HTML::Entities; |
|
5
|
|
|
|
|
29114
|
|
|
5
|
|
|
|
|
387
|
|
37
|
5
|
|
|
5
|
|
3577
|
use JSON; |
|
5
|
|
|
|
|
56482
|
|
|
5
|
|
|
|
|
29
|
|
38
|
5
|
|
|
5
|
|
4511
|
use WWW::Mechanize; |
|
5
|
|
|
|
|
717406
|
|
|
5
|
|
|
|
|
297
|
|
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
########################################################################### |
41
|
|
|
|
|
|
|
# Constants & Variables |
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
my $DOMAIN = 'http://books.google.com'; |
44
|
|
|
|
|
|
|
|
45
|
5
|
|
|
5
|
|
46
|
use constant SEARCH => '/books?jscmd=viewapi&callback=bookdata&bibkeys=ISBN:'; |
|
5
|
|
|
|
|
12
|
|
|
5
|
|
|
|
|
360
|
|
46
|
5
|
|
|
5
|
|
44
|
use constant LB2G => 453.59237; # number of grams in a pound (lb) |
|
5
|
|
|
|
|
12
|
|
|
5
|
|
|
|
|
245
|
|
47
|
5
|
|
|
5
|
|
29
|
use constant OZ2G => 28.3495231; # number of grams in an ounce (oz) |
|
5
|
|
|
|
|
11
|
|
|
5
|
|
|
|
|
229
|
|
48
|
5
|
|
|
5
|
|
30
|
use constant IN2MM => 25.4; # number of inches in a millimetre (mm) |
|
5
|
|
|
|
|
15
|
|
|
5
|
|
|
|
|
11169
|
|
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
my %LANG = ( |
51
|
|
|
|
|
|
|
'cz' => { Publisher => 'Vydavatel', Author => 'Autor', Title => 'Titul', Length => [ 'Délka', qr/\QD\x{e9}lka\E/, 'Délka' ], |
52
|
|
|
|
|
|
|
Pages => [ 'Počet stran:', qr/\QPo\x{10d}et stran:\E/, 'Počet stran:' ] }, |
53
|
|
|
|
|
|
|
'de' => { Publisher => 'Verlag', Author => 'Autor', Title => 'Titel', Length => qr{L.+nge}, Pages => 'Seiten' }, |
54
|
|
|
|
|
|
|
'en' => { Publisher => 'Publisher', Author => 'Author', Title => 'Title', Length => 'Length', Pages => 'pages' }, |
55
|
|
|
|
|
|
|
'es' => { Publisher => 'Editor', Author => 'Autor', Title => 'Título', Length => [ 'N.º de páginas', 'N.º de páginas' ], |
56
|
|
|
|
|
|
|
Pages => [ 'páginas', 'páginas' ] }, |
57
|
|
|
|
|
|
|
'fr' => { Publisher => '.+diteur', Author => 'Auteur', Title => 'Titre', Length => 'Longueur', Pages => 'pages' }, |
58
|
|
|
|
|
|
|
'fi' => { Publisher => 'Kustantaja', Author => 'Kirjoittaja', Title => 'Otsikko', Length => 'Pituus', Pages => 'sivua' }, |
59
|
|
|
|
|
|
|
'nl' => { Publisher => 'Uitgever', Author => 'Auteur', Title => 'Titel', Length => 'Lengte', Pages => [ q{pagina's}, 'pagina's' ] }, |
60
|
|
|
|
|
|
|
'md' => { Publisher => 'Editor', Author => 'Autor', Title => 'Titlu', Length => 'Lungime', Pages => 'pagini' }, |
61
|
|
|
|
|
|
|
'ru' => { Publisher => ['Издатель', qr/\Q\x{418}\x{437}\x{434}\x{430}\x{442}\x{435}\x{43b}\x{44c}\E/, 'Издатель', 'ÐздаÑелÑ' ], |
62
|
|
|
|
|
|
|
Author => 'Автор', Title => 'Название', |
63
|
|
|
|
|
|
|
Length => [ 'Количество страниц', qr/\Q\x{41a}\x{43e}\x{43b}\x{438}\x{447}\x{435}\x{441}\x{442}\x{432}\x{43e} \x{441}\x{442}\x{440}\x{430}\x{43d}\x{438}\x{446}/, 'Количество страниц', 'ÐолиÑеÑÑво ÑÑÑаниÑ' ], |
64
|
|
|
|
|
|
|
Pages => [ 'Всего страниц:', qr/\Q\x{412}\x{441}\x{435}\x{433}\x{43e} \x{441}\x{442}\x{440}\x{430}\x{43d}\x{438}\x{446}:/, 'Всего страниц:', 'ÐÑего ÑÑÑаниÑ', 'ÐÑего ÑÑÑаниÑ:' ] }, |
65
|
|
|
|
|
|
|
'iw' => { Publisher => [ '\x{5d4}\x{5d5}\x{5e6}\x{5d0}\x{5d4}', 'הוצאה' ], |
66
|
|
|
|
|
|
|
Author => 'Author', Title => 'Title', Length => [ qr/\Q\x{5d0}\x{5d5}\x{5e8}\x{5da}\E/, '×ורך', '\x{5d0}\x{5d5}\x{5e8}\x{5da}', 'אורך' ], |
67
|
|
|
|
|
|
|
Pages => [ qr/\Q\x{5e2}\x{5de}\x{5d5}\x{5d3}\x{5d9}\x{5dd}\E/, 'עמודי×', '\x{5e2}\x{5de}\x{5d5}\x{5d3}\x{5d9}\x{5dd}', 'עמודים' ] } |
68
|
|
|
|
|
|
|
); |
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
#-------------------------------------------------------------------------- |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
########################################################################### |
73
|
|
|
|
|
|
|
# Public Interface |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
=head1 METHODS |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
=over 4 |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
=item C |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
Creates a query string, then passes the appropriate form fields to the |
82
|
|
|
|
|
|
|
GoogleBooks server. |
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
The returned page should be the correct catalog page for that ISBN. If not the |
85
|
|
|
|
|
|
|
function returns zero and allows the next driver in the chain to have a go. If |
86
|
|
|
|
|
|
|
a valid page is returned, the following fields are returned via the book hash: |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
isbn (now returns isbn13) |
89
|
|
|
|
|
|
|
isbn10 |
90
|
|
|
|
|
|
|
isbn13 |
91
|
|
|
|
|
|
|
ean13 (industry name) |
92
|
|
|
|
|
|
|
author |
93
|
|
|
|
|
|
|
title |
94
|
|
|
|
|
|
|
book_link |
95
|
|
|
|
|
|
|
image_link |
96
|
|
|
|
|
|
|
pubdate |
97
|
|
|
|
|
|
|
publisher |
98
|
|
|
|
|
|
|
description (if available) |
99
|
|
|
|
|
|
|
pages (if known) |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
The book_link and image_link refer back to the GoogleBooks website. |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
=back |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
=cut |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
sub search { |
108
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
109
|
0
|
|
|
|
|
|
my $isbn = shift; |
110
|
0
|
|
|
|
|
|
my $data; |
111
|
0
|
|
|
|
|
|
$self->found(0); |
112
|
0
|
|
|
|
|
|
$self->book(undef); |
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
# validate and convert into EAN13 format |
115
|
0
|
|
|
|
|
|
my $ean = $self->convert_to_ean13($isbn); |
116
|
0
|
0
|
|
|
|
|
return $self->handler("Invalid ISBN specified") |
117
|
|
|
|
|
|
|
unless($ean); |
118
|
|
|
|
|
|
|
|
119
|
0
|
|
|
|
|
|
my $mech = WWW::Mechanize->new(); |
120
|
0
|
|
|
|
|
|
$mech->agent_alias( 'Linux Mozilla' ); |
121
|
|
|
|
|
|
|
|
122
|
0
|
|
0
|
|
|
|
my $search = ($ENV{GOOGLE_DOMAIN} || $DOMAIN) . SEARCH . $ean; |
123
|
0
|
|
|
|
|
|
eval { $mech->get( $search ) }; |
|
0
|
|
|
|
|
|
|
124
|
0
|
0
|
0
|
|
|
|
return $self->handler("GoogleBooks website appears to be unavailable.") |
|
|
|
0
|
|
|
|
|
125
|
|
|
|
|
|
|
if($@ || !$mech->success() || !$mech->content()); |
126
|
|
|
|
|
|
|
|
127
|
0
|
|
|
|
|
|
my $json = $mech->content(); |
128
|
|
|
|
|
|
|
|
129
|
0
|
0
|
|
|
|
|
return $self->handler("Failed to find that book on GoogleBooks website.") |
130
|
|
|
|
|
|
|
if($json eq 'bookdata({});'); |
131
|
|
|
|
|
|
|
|
132
|
0
|
|
|
|
|
|
$json =~ s/^bookdata\(//; |
133
|
0
|
|
|
|
|
|
$json =~ s/\);$//; |
134
|
|
|
|
|
|
|
|
135
|
0
|
|
|
|
|
|
my $code = decode_json($json); |
136
|
|
|
|
|
|
|
#use Data::Dumper; |
137
|
|
|
|
|
|
|
#print STDERR "\n# code=".Dumper($code); |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
return $self->handler("Failed to find that book on GoogleBooks website.") |
140
|
0
|
0
|
0
|
|
|
|
unless($code->{'ISBN:'.$ean} || $code->{'ISBN:'.$isbn}); |
141
|
|
|
|
|
|
|
|
142
|
0
|
|
|
|
|
|
$data->{url} = $code->{'ISBN:'.$ean }{info_url}; |
143
|
0
|
|
0
|
|
|
|
$data->{url} ||= $code->{'ISBN:'.$isbn}{info_url}; |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
return $self->handler("Failed to find that book on GoogleBooks website.") |
146
|
0
|
0
|
|
|
|
|
unless($data->{url}); |
147
|
|
|
|
|
|
|
|
148
|
0
|
|
|
|
|
|
eval { $mech->get( $data->{url} ) }; |
|
0
|
|
|
|
|
|
|
149
|
0
|
0
|
0
|
|
|
|
return $self->handler("GoogleBooks website appears to be unavailable.") |
|
|
|
0
|
|
|
|
|
150
|
|
|
|
|
|
|
if($@ || !$mech->success() || !$mech->content()); |
151
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
# The Book page |
153
|
|
|
|
|
|
|
#my $html = $mech->content(); |
154
|
0
|
|
|
|
|
|
my $html = encode_entities($mech->content(),'^\n\x20-\x25\x27-\x7e'); |
155
|
0
|
|
|
|
|
|
$html =~ s/\'/'/sig; |
156
|
0
|
|
|
|
|
|
$html =~ s/\\x\(([a-z\d]+)\)/\$1;/sig; |
157
|
0
|
|
|
|
|
|
$html =~ s/7/7/sig; |
158
|
|
|
|
|
|
|
|
159
|
0
|
0
|
|
|
|
|
return $self->handler("Failed to find that book on GoogleBooks website. [$isbn]") |
160
|
|
|
|
|
|
|
if($html =~ m!Sorry, we couldn't find any matches for!si); |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
#use Data::Dumper; |
163
|
|
|
|
|
|
|
#print STDERR "\n# " . Dumper($data); |
164
|
|
|
|
|
|
|
#print STDERR "\n# html=[$html]\n"; |
165
|
|
|
|
|
|
|
|
166
|
0
|
|
|
|
|
|
$data->{url} = $mech->uri(); |
167
|
0
|
|
|
|
|
|
my ($ccTLD) = $data->{url} =~ m{^http://[.\w]+\.google\.(\w\w)\b}; |
168
|
|
|
|
|
|
|
|
169
|
0
|
|
|
|
|
|
my $lang = 'en'; # English (default) |
170
|
0
|
0
|
|
|
|
|
$lang = 'de' if($data->{url} =~ m{^http://[.\w]+\.google\.(de|ch|at)\b}); # German |
171
|
0
|
0
|
|
|
|
|
$lang = 'iw' if($data->{url} =~ m{^http://[.\w]+\.google\.co\.il\b}); # Hebrew |
172
|
0
|
0
|
0
|
|
|
|
$lang = $ccTLD if($ccTLD && $LANG{$ccTLD}); # we have a ccTLD translation |
173
|
|
|
|
|
|
|
|
174
|
0
|
0
|
|
|
|
|
return $self->handler("Language '".uc $lang."'not currently supported, patches welcome.") |
175
|
|
|
|
|
|
|
if($lang =~ m!xx!); |
176
|
|
|
|
|
|
|
|
177
|
0
|
|
|
|
|
|
_match( $html, $data, $lang ); |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
# remove HTML tags |
180
|
0
|
|
|
|
|
|
for(qw(author)) { |
181
|
0
|
0
|
|
|
|
|
next unless(defined $data->{$_}); |
182
|
0
|
|
|
|
|
|
$data->{$_} =~ s!<[^>]+>!!g; |
183
|
|
|
|
|
|
|
} |
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
# trim top and tail |
186
|
0
|
0
|
|
|
|
|
for(keys %$data) { next unless(defined $data->{$_});$data->{$_} =~ s/^\s+//;$data->{$_} =~ s/\s+$//; } |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
# .com (and possibly others) don't always use Google's own CDN |
189
|
0
|
0
|
|
|
|
|
if($data->{image} =~ m!^/!) { |
190
|
0
|
|
|
|
|
|
my $domain = $mech->uri(); |
191
|
0
|
|
|
|
|
|
$domain = s!^(http://[^/]+).*$!$1!; |
192
|
0
|
|
|
|
|
|
$data->{image} = $domain . $data->{image}; |
193
|
0
|
|
|
|
|
|
$data->{thumb} = $data->{image}; |
194
|
|
|
|
|
|
|
} |
195
|
|
|
|
|
|
|
|
196
|
0
|
|
|
|
|
|
my $url = $mech->uri(); |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
my $bk = { |
199
|
|
|
|
|
|
|
'ean13' => $data->{isbn13}, |
200
|
|
|
|
|
|
|
'isbn13' => $data->{isbn13}, |
201
|
|
|
|
|
|
|
'isbn10' => $data->{isbn10}, |
202
|
|
|
|
|
|
|
'isbn' => $data->{isbn13}, |
203
|
|
|
|
|
|
|
'author' => $data->{author}, |
204
|
|
|
|
|
|
|
'title' => $data->{title}, |
205
|
|
|
|
|
|
|
'book_link' => "$url", |
206
|
|
|
|
|
|
|
'image_link' => $data->{image}, |
207
|
|
|
|
|
|
|
'thumb_link' => $data->{thumb}, |
208
|
|
|
|
|
|
|
'pubdate' => $data->{pubdate}, |
209
|
|
|
|
|
|
|
'publisher' => $data->{publisher}, |
210
|
|
|
|
|
|
|
'description' => $data->{description}, |
211
|
|
|
|
|
|
|
'pages' => $data->{pages}, |
212
|
0
|
|
|
|
|
|
'html' => $html |
213
|
|
|
|
|
|
|
}; |
214
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
#use Data::Dumper; |
216
|
|
|
|
|
|
|
#print STDERR "\n# book=".Dumper($bk); |
217
|
|
|
|
|
|
|
|
218
|
0
|
|
|
|
|
|
$self->book($bk); |
219
|
0
|
|
|
|
|
|
$self->found(1); |
220
|
0
|
|
|
|
|
|
return $self->book; |
221
|
|
|
|
|
|
|
} |
222
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
=head2 Private Methods |
224
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
=over 4 |
226
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
=item C<_match> |
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
Pattern matches for book page. |
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
=back |
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
=cut |
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
sub _match { |
236
|
0
|
|
|
0
|
|
|
my ($html, $data, $lang) = @_; |
237
|
0
|
|
|
|
|
|
my ($publisher); |
238
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
#print "\n# lang=$lang\n"; |
240
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
# Some pages can present publisher text in multiple styles |
242
|
0
|
0
|
|
|
|
|
my @pubs = ref($LANG{$lang}->{Publisher}) eq 'ARRAY' ? @{$LANG{$lang}->{Publisher}} : ($LANG{$lang}->{Publisher}); |
|
0
|
|
|
|
|
|
|
243
|
0
|
|
|
|
|
|
for my $pub (@pubs) { |
244
|
0
|
|
|
|
|
|
($publisher) = $html =~ m! | (?:]*>)?$pub(?:)? | (?:]*>)?([^<]+)(?:)? | !si;
245
|
0
|
0
|
|
|
|
|
last if($publisher); |
246
|
|
|
|
|
|
|
} |
247
|
0
|
0
|
|
|
|
|
if($publisher) { |
248
|
0
|
|
|
|
|
|
my @publist = split(qr/\s*,\s*/,$publisher); |
249
|
0
|
|
|
|
|
|
$data->{publisher} = $publist[0]; |
250
|
0
|
|
|
|
|
|
$data->{pubdate} = $publist[-1]; |
251
|
|
|
|
|
|
|
} |
252
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
# Some pages can present length/pages text in multiple styles |
254
|
0
|
0
|
|
|
|
|
my @lengths = ref($LANG{$lang}->{Length}) eq 'ARRAY' ? @{$LANG{$lang}->{Length}} : ($LANG{$lang}->{Length}); |
|
0
|
|
|
|
|
|
|
255
|
0
|
0
|
|
|
|
|
my @pages = ref($LANG{$lang}->{Pages}) eq 'ARRAY' ? @{$LANG{$lang}->{Pages}} : ($LANG{$lang}->{Pages}); |
|
0
|
|
|
|
|
|
|
256
|
0
|
|
|
|
|
|
for my $length (@lengths) { |
257
|
0
|
|
|
|
|
|
for my $page (@pages) { |
258
|
0
|
|
|
|
|
|
($data->{pages}) = $html =~ m! | (?:]*>)?$length(?:)? | (?:]*>)?(\d+)\s*$page(?:)? | !si;
259
|
0
|
0
|
|
|
|
|
last if($data->{pages}); |
260
|
0
|
|
|
|
|
|
($data->{pages}) = $html =~ m! | (?:]*>)?$length(?:)? | (?:]*>)?\s*$page\s+(\d+)(?:)? | !si;
261
|
0
|
0
|
|
|
|
|
last if($data->{pages}); |
262
|
|
|
|
|
|
|
} |
263
|
0
|
0
|
|
|
|
|
last if($data->{pages}); |
264
|
|
|
|
|
|
|
} |
265
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
# get ISBN styles |
267
|
0
|
|
|
|
|
|
my ($isbns) = $html =~ m! | (?:]*>)?ISBN(?:)? | (?:]*>)?([^<]+)(?:)? | !i;
268
|
0
|
|
|
|
|
|
my (@isbns) = split(qr/\s*,\s*/,$isbns); |
269
|
0
|
|
|
|
|
|
for my $value (@isbns) { |
270
|
0
|
0
|
|
|
|
|
$data->{isbn13} = $value if(length $value == 13); |
271
|
0
|
0
|
|
|
|
|
$data->{isbn10} = $value if(length $value == 10); |
272
|
|
|
|
|
|
|
} |
273
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
#use Data::Dumper; |
275
|
|
|
|
|
|
|
#print STDERR "\n# isbns=[$isbns]"; |
276
|
|
|
|
|
|
|
#print STDERR "\n# " . Dumper($data); |
277
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
# get other fields |
279
|
0
|
|
|
|
|
|
($data->{image}) = $html =~ m!]+id=summary-frontcover[^>]*> !i; |
280
|
0
|
0
|
|
|
|
|
($data->{image}) = $html =~ m!!i unless($data->{image}); |
281
|
0
|
|
|
|
|
|
($data->{author}) = $html =~ m! | (?:]*>)?$LANG{$lang}->{Author}(?:)? | (.*?) | !i;
282
|
0
|
0
|
|
|
|
|
($data->{author}) = $html =~ m! | ([^<]+) | !si unless($data->{author});
283
|
0
|
|
|
|
|
|
($data->{title}) = $html =~ m! | (?:]*>)?$LANG{$lang}->{Title}(?:)? | (?:]*>)?([^<]+)(?:)?!i; |
284
|
0
|
0
|
|
|
|
|
($data->{title}) = $html =~ m!! unless($data->{title}); |
285
|
0
|
|
|
|
|
|
($data->{description}) = $html =~ m!!si; |
286
|
|
|
|
|
|
|
|
287
|
0
|
|
|
|
|
|
$data->{author} =~ s/"//g; |
288
|
0
|
|
|
|
|
|
$data->{thumb} = $data->{image}; |
289
|
|
|
|
|
|
|
} |
290
|
|
|
|
|
|
|
|
291
|
|
|
|
|
|
|
1; |
292
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
__END__ |