rewrite COBISS into perl object
[Biblio-Z3950.git] / COBISS.pm
1 package COBISS;
2
3 use warnings;
4 use strict;
5
6 use WWW::Mechanize;
7 use MARC::Record;
8 use Data::Dump qw/dump/;
9
10 binmode STDOUT, ':utf8';
11
12 sub new {
13     my ( $class ) = @_;
14     my $self = {};
15     bless $self, $class;
16     return $self;
17 }
18
19
20 my $cobiss_marc21 = {
21         '010' => { a => [ '020', 'a' ] },
22          200  => {
23                         a => [  245 , 'a' ],
24                         f => [  245 , 'f' ],
25         },
26          205  => { a => [  250 , 'a' ] },
27          210  => {
28                 a => [  260 , 'a' ],
29                 c => [  260 , 'b' ],
30                 d => [  260 , 'c' ],
31         },
32         215 => {
33                 a => [  300 , 'a' ],
34                 c => [  300 , 'b' ],
35                 d => [  300 , 'c' ],
36         },
37         700 => {
38                 a => [  100 , 'a' ],
39         },
40 };
41
42 sub diag {
43         print "# ", @_, $/;
44 }
45
46 # Koha Z39.50 query:
47 #
48 # Bib-1 @and @and @and @and @and @and @and @or
49 # @attr 1=8 isbn-issn 
50 # @attr 1=7 isbn-issn 
51 # @attr 1=4 title 
52 # @attr 1=1003 author 
53 # @attr 1=16 dewey 
54 # @attr 1=21 subject-holding 
55 # @attr 1=12 control-no 
56 # @attr 1=1007 standard-id 
57 # @attr 1=1016 any
58
59 sub usemap {{
60         8               => 'BN',        # FIXME check
61         7               => 'SN',        # FIXME check
62         4               => 'TI',
63         1003    => 'TI',
64         16              => 'CU',
65         21              => 'SU',
66 #       12              => '',
67 #       1007    => '',
68 #       1016    => '',
69
70 }};
71
72 sub search {
73         my ( $self, $query ) = @_;
74
75         die "need query" unless defined $query;
76
77         my $url = 'http://cobiss.izum.si/scripts/cobiss?ukaz=GETID&lani=en';
78
79 diag "get $url";
80
81         my $mech = $self->{mech} = WWW::Mechanize->new();
82         my $hits;
83         $mech->get( $url );
84
85 diag "got session";
86
87         $mech->follow_link( text_regex => qr/union/ );
88
89 diag "switch to advanced form (select)";
90
91         $mech->follow_link( url_regex => qr/mode=3/ );
92
93 diag "submit search $query";
94
95         $mech->submit_form(
96                 fields => {
97                         'SS1' => $query,
98                 },
99         );
100
101         $hits = 0;
102         if ( $mech->content =~ m{hits:\s*<b>\s*(\d+)\s*</b>}s ) {
103                 $hits = $1;
104         } else {
105                 diag "get't find results in ", $mech->content;
106                 return;
107         }
108
109 diag "got $hits results, get first one";
110
111         $mech->follow_link( url_regex => qr/ukaz=DISP/ );
112
113 diag "in COMARC format";
114
115         $mech->follow_link( url_regex => qr/fmt=13/ );
116
117         return $hits;
118 }
119
120
121 sub next_marc {
122         my ($self,$format) = @_;
123
124         my $mech = $self->{mech} || die "no mech?";
125
126         $format ||= 'unimarc';
127
128         die "unknown format: $format" unless $format =~ m{(uni|us)marc};
129
130         my $comarc;
131
132         if ( $mech->content =~ m{<pre>\s*(.+?(\d+)\.\s+ID=(\d+).+?)\s*</pre>}s ) {
133
134                 my $comarc = $1;
135                 my $nr = $2;
136                 my $id = $3;
137
138 diag "fetch_marc $nr [$id] $format";
139
140                 $comarc =~ s{</?b>}{}gs;
141                 $comarc =~ s{<font[^>]*>}{<s>}gs;
142                 $comarc =~ s{</font>}{<e>}gs;
143
144                 open(my $out, '>:utf8', "comarc/$id");
145                 print $out $comarc;
146                 close($out);
147
148                 print $comarc;
149
150                 my $marc = MARC::Record->new;
151
152                 foreach my $line ( split(/[\r\n]+/, $comarc) ) {
153
154                         if ( $line !~ s{^(\d\d\d)([01 ])([01 ])}{} ) {
155                                 diag "SKIP: $line";
156                         } else {
157                                 our @f = ( $1, $2, $3 );
158                                 $line .= "<eol>";
159
160                                 if ( $format eq 'unimarc' ) {
161
162                                         diag dump(@f), "line: $line";
163                                         sub sf_uni {
164                                                 warn "sf ",dump(@_);
165                                                 push @f, @_;
166                                         }
167                                         $line =~ s{<s>(\w)<e>([^<]+)\s*}{sf_uni($1, $2)}ges;
168                                         diag "f:", dump(@f), " left: |$line|";
169                                         $marc->add_fields( @f );
170
171                                 } elsif ( $format eq 'usmarc' ) {
172
173                                         my ( $f, $i1, $i2 ) = @f;
174
175                                         our $out = {};
176
177                                         sub sf_us {
178                                                 my ($f,$sf,$v) = @_;
179                                                 if ( my $m = $cobiss_marc21->{$f}->{$sf} ) {
180                                                         push @{ $out->{ $m->[0] } }, ( $m->[1], $v );
181                                                 }
182                                                 return;
183                                         }
184                                         $line =~ s{<s>(\w)<e>([^<]+)\s*}{sf_us($f,$1, $2)}ges;
185
186                                         diag "converted marc21 ",dump( $out );
187
188                                         foreach my $f ( keys %$out ) {
189                                                 $marc->add_fields( $f, $i1, $i2, @{ $out->{$f} } );
190                                         }
191                                 }
192                         }
193                 }
194
195                 my $path = "marc/$id.$format";
196
197                 open($out, '>:utf8', $path);
198                 print $out $marc->as_usmarc;
199                 close($out);
200
201                 diag "created $path ", -s $path, " bytes";
202
203                 diag $marc->as_formatted;
204
205                 $nr++;
206                 $mech->follow_link( url_regex => qr/rec=$nr/ );
207
208                 return $marc->as_usmarc;
209         } else {
210                 die "can't fetch COMARC format from ", $mech->content;
211         }
212
213 }
214
215 1;