ignore ssl certificate errors
[Biblio-Z3950.git] / GoogleBooks.pm
1 package GoogleBooks;
2
3 use warnings;
4 use strict;
5
6 use MARC::Record;
7 use Data::Dump qw/dump/;
8 use JSON::XS;
9
10 use base 'Scraper';
11
12 my $pageCount_suffix = 'p.'; # English
13 $pageCount_suffix = ' str.'; # Croatian
14
15 my $debug = $ENV{DEBUG} || 0;
16
17 sub diag {
18         warn "# ", @_, $/;
19 }
20
21 # based on http://code.google.com/apis/books/docs/v1/using.html#PerformingSearch
22 #
23 # https://www.googleapis.com/books/v1/volumes?q=search+terms
24 #
25 # This request has a single required parameter:
26 #
27 # q - Search for volumes that contain this text string. There are special keywords you can specify in the search terms to search in particular fields, such as:
28 #     intitle: Returns results where the text following this keyword is found in the title.
29 #     inauthor: Returns results where the text following this keyword is found in the author.
30 #     inpublisher: Returns results where the text following this keyword is found in the publisher.
31 #     subject: Returns results where the text following this keyword is listed in the category list of the volume.
32 #     isbn: Returns results where the text following this keyword is the ISBN number.
33 #     lccn: Returns results where the text following this keyword is the Library of Congress Control Number.
34 #     oclc: Returns results where the text following this keyword is the Online Computer Library Center number.
35 #
36
37 # Koha Z39.50 query:
38 #
39 # Bib-1 @and @and @and @and @and @and @and @or
40 # @attr 1=4 title 
41 # @attr 1=7 isbn
42 # @attr 1=8 issn 
43 # @attr 1=1003 author 
44 # @attr 1=16 dewey 
45 # @attr 1=21 subject-holding 
46 # @attr 1=12 control-no 
47 # @attr 1=1007 standard-id 
48 # @attr 1=1016 any
49
50 sub usemap {{
51         4               => 'intitle:',
52         7               => 'isbn:',
53         8               => 'isbn:', # FIXME?
54         1003    => 'inauthor:',
55 #       16              => '',
56         21              => 'subject:',
57         12              => 'lccn:',
58 #       1007    => '',
59         1016    => '',
60 }};
61
62 sub search {
63         my ( $self, $query ) = @_;
64
65         die "need query" unless defined $query;
66
67         my $url = 'https://www.googleapis.com/books/v1/volumes?q=' . $query;
68
69 diag "get $url";
70
71         my $mech = $self->{mech} || die "no mech?";
72         $mech->get( $url );
73
74         my $json = decode_json $mech->content;
75         diag "# json = ", dump($json) if $debug;
76
77         my $hits = 0;
78
79         if ( exists $json->{items} ) {
80                 $hits = $#{ $json->{items} } + 1;
81         } else {
82                 diag "get't find results in ", $mech->content;
83                 return;
84         }
85
86 diag "got $hits results, get first one";
87
88         $self->{_json} = $json;
89         $self->{_json_item} = 0;
90
91         return $self->{hits} = $hits;
92 }
93
94
95 sub next_marc {
96         my ($self,$format) = @_;
97
98         $format ||= 'marc';
99
100         my $item = $self->{_json}->{items}->[ $self->{_json_item}++ ];
101
102         warn "# item = ",dump($item) if $debug;
103
104         my $id = $item->{id} || die "no id";
105
106         my $marc = MARC::Record->new;
107         $marc->encoding('utf-8');
108
109         if ( my $vi = $item->{volumeInfo} ) {
110
111                 my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
112
113                 $marc->add_fields('008',sprintf("%02d%02d%02ds%04d%25s%-3s",
114                                 $year % 100, $mon + 1, $mday, substr($vi->{publishedDate},0,4), ' ', $vi->{language}));
115
116                 if ( ref $vi->{industryIdentifiers} eq 'ARRAY' ) {
117                         foreach my $i ( @{ $vi->{industryIdentifiers} } ) {
118                                 if ( $i->{type} =~ m/ISBN/i ) {
119                                         $marc->add_fields('020',' ',' ','a' => $i->{identifier} )
120                                 } else {
121                                         $marc->add_fields('035',' ',' ','a' => $i->{identifier} )
122                                 }
123                         }
124                 }
125
126                 my $first_author;
127                 if ( ref $vi->{authors} eq 'ARRAY' ) {
128                         $first_author = shift @{ $vi->{authors} };
129                         $marc->add_fields(100,'0',' ','a' => $first_author );
130                         $marc->add_fields(700,'0',' ','a' => $_ ) foreach @{ $vi->{authors} };
131                 }
132
133                 $marc->add_fields(245, ($first_author ? '1':'0') ,' ',
134                         'a' => $vi->{title},
135                         $vi->{subtitle} ? ( 'b' => $vi->{subtitle} ) : (),
136                 );
137
138                 if ( exists $vi->{publisher} or exists $vi->{publishedDate} ) {
139                         $marc->add_fields(260,' ',' ',
140                                 $vi->{publisher} ? ( 'b' => $vi->{publisher} ) : (),
141                                 $vi->{publishedDate} ? ( 'c' => $vi->{publishedDate} ) : ()
142                         );
143                 }
144
145                 $marc->add_fields(300,' ',' ','a' => $vi->{pageCount} . $pageCount_suffix ) if $vi->{pageCount};
146                 
147                 $marc->add_fields(520,' ',' ','a' => $vi->{description} ) if $vi->{description};
148
149                 if ( ref $vi->{categories} eq 'ARRAY' ) {
150                         $marc->add_fields(650,' ','4','a' => $_ ) foreach @{ $vi->{categories} };
151                 }
152
153                 if ( exists $vi->{imageLinks} ) {
154
155                         $marc->add_fields(856,'4','2',
156                                 '3'=> 'Image link',
157                                 'u' => $vi->{imageLinks}->{smallThumbnail},
158                                 'x' => 'smallThumbnail',
159                         ) if exists $vi->{imageLinks}->{smallThumbnail};
160                         $marc->add_fields(856,'4','2',
161                                 '3'=> 'Image link',
162                                 'u' => $vi->{imageLinks}->{thumbnail},
163                                 'x' => 'thumbnail',
164                         ) if exists $vi->{imageLinks}->{thumbnail};
165
166                 } # if imageLinks
167
168                 $marc->add_fields(856,'4','2',
169                         '3'=> 'Info link',
170                         'u' => $vi->{infoLink},
171                 );
172                 $marc->add_fields(856,'4','2',
173                         '3'=> 'Show reviews link',
174                         'u' => $vi->{showReviewsLink},
175                 );
176
177                 my $leader = $marc->leader;
178                 warn "# leader [$leader]";
179                 $leader =~ s/^(....).../$1nam/;
180                 $marc->leader( $leader );
181
182         } else {
183                 warn "ERROR: no volumeInfo in ",dump($item);
184         }
185
186         $marc->add_fields( 856, ' ', ' ', 'u' => $item->{accessInfo}->{webReaderLink} );
187 #       $marc->add_fields( 520, ' ', ' ', 'a' => $item->{searchInfo}->{textSnippet} ); # duplicate of description
188
189 #       diag "# hash ",dump($hash);
190         diag "# marc ", $marc->as_formatted;
191
192         $self->save_marc( "$id.marc", $marc->as_usmarc );
193
194         return $id;
195
196 }
197
198 1;