ignore ssl certificate errors
[Biblio-Z3950.git] / Aleph.pm
1 package Aleph;
2
3 use warnings;
4 use strict;
5
6 use MARC::Record;
7 use Data::Dump qw/dump/;
8
9 use Scraper;
10 use base 'Scraper';
11
12 sub diag {
13         warn "# ", @_, $/;
14 }
15
16 # Koha Z39.50 query:
17 #
18 # Bib-1 @and @and @and @and @and @and @and @or
19 # @attr 1=4 title 
20 # @attr 1=7 isbn
21 # @attr 1=8 issn 
22 # @attr 1=1003 author 
23 # @attr 1=16 dewey 
24 # @attr 1=21 subject-holding 
25 # @attr 1=12 control-no 
26 # @attr 1=1007 standard-id 
27 # @attr 1=1016 any
28
29 # LCC - Klasifikacija Kongresne knjižnice 
30 # LCN - Signatura Kongresne knjižnice
31 # DDC - Deweyjeva klasifikacija 
32 # TIT - Naslovi 
33 # AUT - Autori 
34 # IMP - Impresum
35 # SUB - Predmetnice
36 # SRS - Nakladnička cjelina 
37 # LOC - Lokacija 
38 # WRD - Riječi 
39 # WTI - Riječi u polju naslova 
40 # WAU - Riječi u polju autora 
41 # WPE - Riječi u polju individualnog autora 
42 # WCO - Riječi u polju korporativnog autora 
43 # WME - Riječi u polju sastanka 
44 # WUT - Riječi u polju jedinstvenog naslova 
45 # WPL - Riječi u polju mjesta izdavanja 
46 # WPU - Riječi u polju nakladnika 
47 # WSU - Riječi u polju predmetnica 
48 # WSM - Riječi u predmetnicama MeSH-a 
49 # WST - Riječi u polju status
50 # WGA - Riječi u geografskim odrednicama 
51 # WYR - Godina izdavanja
52
53 sub usemap {{
54         4               => 'WTI=',
55         7               => 'ISBN=',
56         8               => 'ISSN=',
57         1003    => 'AUT=',
58         16              => 'DDC=',
59         21              => 'SUB=',
60         12              => 'LCN=',
61 #       1007    => '',
62         1016    => 'WRD=',
63 }};
64
65 our $session_id;
66
67 sub search {
68         my ( $self, $query ) = @_;
69
70         die "need query" unless defined $query;
71
72         $session_id ||= int rand(1000000000);
73         # FIXME allocate session just once
74         my $url = 'https://katalog.nsk.hr/F?RN=' . $session_id;
75         # fake JavaScript code on page which creates random session
76
77 diag "get $url";
78
79         my $mech = $self->{mech} || die "no mech?";
80         $mech->get( $url );
81
82 diag "advanced search";
83
84         $mech->follow_link( url_regex => qr/find-c/ );
85
86         my $database = $self->{database};
87
88         if ( $mech->content =~ m{Requested library is unavailable at the moment} ) {
89                 warn "ERROR: default database not available, try to swith to $database\n";
90                 $self->save_content;
91                 $mech->follow_link( url_regex => qr/local_base=$database/i );
92                 diag "re-try advanced search";
93                 $mech->follow_link( url_regex => qr/find-c/ );
94         }
95
96 diag "submit search [$query] on ", $self->{database};
97
98
99         $mech->submit_form(
100                 fields => {
101                         'ccl_term' => $query,
102                         'local_base' => $self->{database},
103                 },
104         );
105
106         my $hits = 0;
107         if ( $mech->content =~ m{ukupno\s+(\d+).*do\s+(\d+)} ) { # FIXME Many results in Crotian
108                 $hits = $1;
109                 $hits = $2 if $2 && $2 < $1; # correct for max. results
110         } elsif ( $mech->content =~ m{(\d+)\s+od\s+(\d+)} ) { # FIXME single result in Croatian
111                 $hits = $2;
112         } else {
113                 diag "get't find results in ", $mech->content;
114                 return;
115         }
116
117 diag "got $hits results, get first one";
118
119         $mech->follow_link( url_regex => qr/set_entry=000001/ );
120
121 diag "in MARC format";
122
123         $mech->follow_link( url_regex => qr/format=001/ );
124
125         return $self->{hits} = $hits;
126 }
127
128
129 our ( $hash, $marc );
130
131 sub next_marc {
132         my ($self,$format) = @_;
133
134         $format ||= 'marc';
135
136         my $mech = $self->{mech} || die "no mech?";
137
138 #warn "## ", $mech->content;
139
140         if ( $mech->content =~ m{Zapis\s+(\d+)}s ) {
141
142                 my $nr = $1;
143
144 warn "parse $nr";
145
146                 $marc = MARC::Record->new;
147                 $marc->encoding('utf-8');
148                 $hash = {};
149
150                 my $html = $mech->content;
151
152                 sub field {
153                         my ( $f, $v ) = @_;
154                         $v =~ s/\Q&nbsp;\E/ /gs;
155                         $v =~ s/\s+$//gs;
156 warn "## $f\t$v\n";
157                         $hash->{$f} = $v;
158
159                         if ( $f eq 'LDR' ) {
160                                 $marc->leader( $v );
161                                 return;
162                         }
163
164                         if ( $f =~ m/\D/ ) {
165                                 warn "$f not numeric!";
166                                 return;
167                         }
168
169                         if ( $v !~ s/^\|// ) { # no subfields
170                                 $marc->add_fields( $f, $v );
171 warn "## ++ ", dump( $f, $v );
172                                 return;
173                         }
174
175                         my ($i1,$i2) = (' ',' ');
176                         ($i1,$i2) = ($2,$3) if $f =~ s/^(...)(.)?(.)?/$1/;
177                         $i1 ||= ' ';
178                         $i2 ||= ' ';
179                         my @sf = split(/\|/, $v);
180                         @sf = map { s/^(\w)\s+//; { $1 => $_ } } @sf;
181 #warn "## sf = ", dump(@sf);
182                         $marc->add_fields( $f, $i1, $i2, @sf );
183 warn "## ++ ", dump( $f, $i1, $i2, @sf );
184                 }
185
186                 $html =~ s|<tr>\s*<td class=td1 id=bold[^>]*>(.+?)</td>\s*<td class=td1>(.+?)</td>|field($1,$2)|ges;
187                 diag "# hash ",dump($hash);
188                 diag "# marc ", $marc->as_formatted;
189
190                 my $id = $hash->{SYS} || die "no SYS";
191
192                 $self->save_marc( "$id.marc", $marc->as_usmarc );
193
194                 if ( $nr < $self->{hits} ) {
195                         $nr++;
196                         diag "follow link to next record $nr";
197                         $mech->follow_link( url_regex => qr/set_entry=0*$nr/ );
198                 }
199
200                 return $id;
201         } else {
202                 die "can't fetch COMARC format from ", $mech->content;
203         }
204
205 }
206
207 1;