File Coverage

blib/lib/WWW/Hatena/Scraper.pm
Criterion Covered Total %
statement 22 24 91.6
branch n/a
condition n/a
subroutine 8 8 100.0
pod n/a
total 30 32 93.7


line stmt bran cond sub pod time code
1             package WWW::Hatena::Scraper;
2              
3 1     1   6 use strict;
  1         2  
  1         34  
4 1     1   5 use warnings;
  1         2  
  1         25  
5 1     1   5 use vars qw($VERSION);
  1         2  
  1         43  
6             $VERSION = '0.01';
7              
8 1     1   907 use LWP::UserAgent;
  1         61801  
  1         40  
9 1     1   25982 use HTTP::Cookies;
  1         18486  
  1         38  
10 1     1   11 use Carp;
  1         2  
  1         233  
11 1     1   7 use vars qw($canssl);
  1         2  
  1         55  
12             BEGIN {
13 1     1   866 eval {use Crypt::SSLeay;};
  0            
  0            
14             $canssl = $@;
15             }
16              
17             use constant LOGIN_URL => 'http://www.hatena.ne.jp/login';
18             use constant LABO_LOGIN_URL => 'http://www.hatelabo.jp/login';
19             use constant LOGOUT_URL => 'http://www.hatena.ne.jp/logout';
20             use constant LABO_LOGOUT_URL => 'http://www.hatelabo.jp/logout';
21             use constant USER_CHECK_URL => 'http://hatena.ne.jp/';
22             use constant LABO_USER_CHECK_URL => 'http://hatelabo.jp/';
23              
24              
25             sub new {
26             my $self = shift;
27              
28             $self = bless {},$self unless (ref $self);
29              
30             my %opts = @_;
31             $self->ua(delete $opts{ua});
32             $self->user_check_code(delete $opts{user_check_code});
33             $self->{'debug'} = delete $opts{debug};
34             my $labo = delete $opts{labo};
35             $self->user_check_url($opts{user_check_url} ? delete $opts{user_check_url} : $labo ? LABO_USER_CHECK_URL : USER_CHECK_URL);
36             $self->logout_url($labo ? LABO_LOGOUT_URL : LOGOUT_URL);
37             my $login = $labo ? LABO_LOGIN_URL : LOGIN_URL;
38             $login =~ s/^http/https/ if ($canssl);
39             $self->login_url($login);
40              
41             Carp::croak("Unknown options: " . join(", ", keys %opts)) if %opts;
42              
43             return $self;
44             }
45             sub rk { &_getset; }
46             sub user { &_getset; }
47             sub user_check_code { &_getset; }
48             sub user_check_url { &_getset; }
49             sub _ua { &_getset; }
50             sub login_url { &_getset; }
51             sub logout_url { &_getset; }
52             sub _getset {
53             my $self = shift;
54             my $param = (caller(1))[3];
55             $param =~ s/.+:://;
56              
57             if (@_) {
58             my $val = shift;
59             Carp::croak("Too many parameters") if @_;
60             $self->{$param} = $val;
61             }
62             return $self->{$param};
63             }
64             sub _fail {
65             my $self = shift;
66             my ($code, $text) = @_;
67              
68             $text ||= {
69             'cannot_login' => "Cannot login by this ID/Password.",
70             'rk_invalid' => "Cookie value is invalid or expired.",
71             'no_url' => "Url is not given.",
72             'no_url' => "No urls are given.",
73             'no_rk' => "No cookies are given (Maybe not logined)",
74             }->{$code};
75              
76             $self->{'last_errcode'} = $code;
77             $self->{'last_errtext'} = $text;
78              
79             $self->_debug("fail($code) $text");
80             wantarray ? () : undef;
81             }
82             sub _debug {
83             my $self = shift;
84             return unless $self->{debug};
85              
86             if (ref $self->{debug} eq "CODE") {
87             $self->{'debug'}->($_[0]);
88             } else {
89             my $class = ref($self);
90             print STDERR "[DEBUG $class] $_[0]\n";
91             }
92             }
93             sub err {
94             my $self = shift;
95             $self->{'last_errcode'} . ": " . $self->{'last_errtext'};
96             }
97             sub errcode {
98             my $self = shift;
99             $self->{'last_errcode'};
100             }
101             sub errtext {
102             my $self = shift;
103             $self->{'last_errtext'};
104             }
105             sub ua {
106             my $self = shift;
107             my $ua = shift if @_;
108             Carp::croak("Too many parameters") if @_;
109              
110             if (!$self->{'_ua'}) {
111             $self->{'_ua'} = $ua || LWP::UserAgent->new();
112             }
113             $self->{'_ua'};
114             }
115             sub jar {
116             my $self = shift;
117             $self->{'_jar'} = HTTP::Cookies->new unless ($self->{_jar});
118             $self->{'_jar'};
119             }
120              
121             sub parse_rk {
122             my $self = shift;
123             my $res = shift;
124             my $jar = $self->jar;
125             $jar->extract_cookies($res);
126             $jar->scan(sub{ $self->rk($_[2]) if ($_[1] eq 'rk') });
127             $self->rk;
128             }
129              
130             sub parse_user {
131             my $self = shift;
132             my $parser = $self->user_check_code || sub {
133             my $self = shift;
134             my $content = shift;
135             my ($user) = $content =~ /[^\n]+\s*([^<]+)<\/strong>\s*<\/a>[^\n]+<\/td>/m;
136             $self->{'user'} = $user;
137             };
138            
139             my $content = $self->get_content($self->user_check_url) or return;
140             return $parser->($self,$content);
141             }
142              
143             sub login {
144             my $self = shift;
145             if (@_ == 1) {
146             $self->rk(shift);
147             } elsif (@_ == 2) {
148             my $id = shift;
149             my $pw =shift;
150              
151             $self->get_content($self->login_url,"mode=enter&key=${id}&password=${pw}") or return;
152             return $self->_fail('cannot_login') unless ($self->rk);
153             } elsif (@_ > 2) {
154             croak ("Too many parameters");
155             }
156             $self->parse_user or return $self->_fail('rk_invalid');
157             }
158              
159             sub logout {
160             my $self = shift;
161             my $res = $self->get_content($self->logout_url);
162             $self->{rk} = undef;
163             $self->{user} = undef;
164             return $res;
165             }
166              
167             sub get_content {
168             my $self = shift;
169             my $url = shift;
170             my $content = shift;
171             croak ("Too many parameters") if (@_);
172             return $self->_fail('no_url') unless ($url);
173             return $self->_fail('no_rk') if (($url ne $self->login_url) && !($self->rk));
174              
175             my $h = HTTP::Headers->new(Cookie => $self->rk ? "rk=".$self->rk : '') ;
176             $h->content_type('application/x-www-form-urlencoded') if (defined($content));
177             my $r = defined($content) ? HTTP::Request->new("POST",$url,$h,$content) : HTTP::Request->new("GET",$url,$h);
178             my $res = $self->ua->request($r);
179             return $self->_fail('request_error',$res->message) if (!$res->is_success);
180              
181             $self->parse_rk($res);
182             return $res->content;
183             }
184              
185             1;
186             __END__