lib/WWW/Mixi/Scraper/Plugin.pm | |||
---|---|---|---|
Criterion | Covered | Total | % |
statement | 48 | 121 | 39.6 |
branch | 6 | 48 | 12.5 |
condition | 0 | 17 | 0.0 |
subroutine | 11 | 24 | 45.8 |
pod | 7 | 7 | 100.0 |
total | 72 | 217 | 33.1 |
line | stmt | bran | cond | sub | pod | time | code |
---|---|---|---|---|---|---|---|
1 | package WWW::Mixi::Scraper::Plugin; | ||||||
2 | |||||||
3 | 1 | 1 | 9 | use strict; | |||
1 | 2 | ||||||
1 | 30 | ||||||
4 | 1 | 1 | 5 | use warnings; | |||
1 | 1 | ||||||
1 | 22 | ||||||
5 | 1 | 1 | 869 | use Web::Scraper; | |||
1 | 184574 | ||||||
1 | 6 | ||||||
6 | 1 | 1 | 820 | use String::CamelCase qw( decamelize ); | |||
1 | 649 | ||||||
1 | 84 | ||||||
7 | 1 | 1 | 389 | use WWW::Mixi::Scraper::Utils qw( _force_arrayref _uri _datetime ); | |||
1 | 2 | ||||||
1 | 182 | ||||||
8 | |||||||
9 | sub import { | ||||||
10 | 21 | 21 | 622 | my $class = shift; | |||
11 | 21 | 38 | my $pkg = caller; | ||||
12 | |||||||
13 | 21 | 131 | my @subs = qw( | ||||
14 | new parse | ||||||
15 | scraper process process_first result | ||||||
16 | get_content post_process | ||||||
17 | validator build_uri | ||||||
18 | html_or_text _extract_name | ||||||
19 | ); | ||||||
20 | |||||||
21 | 1 | 1 | 17 | no strict 'refs'; | |||
1 | 2 | ||||||
1 | 28 | ||||||
22 | 1 | 1 | 5 | no warnings 'redefine'; | |||
1 | 2 | ||||||
1 | 668 | ||||||
23 | 21 | 33 | foreach my $sub ( @subs ) { | ||||
24 | 252 | 232 | *{"$pkg\::$sub"} = *{"$class\::$sub"}; | ||||
252 | 10282 | ||||||
252 | 1157 | ||||||
25 | } | ||||||
26 | } | ||||||
27 | |||||||
28 | sub new { | ||||||
29 | 0 | 0 | 1 | 0 | my ($class, %options) = @_; | ||
30 | |||||||
31 | 0 | 0 | bless \%options, $class; | ||||
32 | } | ||||||
33 | |||||||
34 | 0 | 0 | 0 | 1 | 0 | sub html_or_text { shift->{mode} || 'HTML' } | |
35 | |||||||
36 | sub parse { | ||||||
37 | 0 | 0 | 1 | 0 | my $self = shift; | ||
38 | |||||||
39 | 0 | 0 | my $res = $self->scrape($self->get_content(@_)); | ||||
40 | |||||||
41 | 0 | 0 | 0 | return ( wantarray and ref $res eq 'ARRAY' ) | |||
42 | 0 | 0 | 0 | 0 | ? @{ $res || [] } | ||
43 | : $res; | ||||||
44 | } | ||||||
45 | |||||||
46 | sub get_content { | ||||||
47 | 0 | 0 | 1 | 0 | my ($self, %options) = @_; | ||
48 | |||||||
49 | 0 | 0 | my $content = delete $options{html}; | ||||
50 | |||||||
51 | 0 | 0 | 0 | unless ( $content ) { | |||
52 | 0 | 0 | $content = $self->{mech}->get_content($self->build_uri(%options)); | ||||
53 | } | ||||||
54 | 0 | 0 | 0 | die "no content" unless $content; | |||
55 | |||||||
56 | # XXX: preserve some tags like ? |
||||||
57 | # $content =~ s/ ]*)?>/\n/g; # at least preserve as a space |
||||||
58 | 0 | 0 | $content =~ s/ / /g; # as it'd be converted as '?' | ||||
59 | |||||||
60 | 0 | 0 | return $content; | ||||
61 | } | ||||||
62 | |||||||
63 | sub build_uri { | ||||||
64 | 0 | 0 | 1 | 0 | my ($self, %query) = @_; | ||
65 | |||||||
66 | 0 | 0 | my ($name) = (ref $self) =~ /::(\w+)$/; | ||||
67 | 0 | 0 | my $path = sprintf '/%s.pl', decamelize($name); | ||||
68 | 0 | 0 | my $uri = URI->new($path); | ||||
69 | |||||||
70 | 0 | 0 | foreach my $key ( keys %query ) { | ||||
71 | 0 | 0 | 0 | if ( $self->_is_valid( $key, $query{$key} ) ) { | |||
72 | 0 | 0 | $uri->query_param( $key => $query{$key} ); | ||||
73 | } | ||||||
74 | } | ||||||
75 | |||||||
76 | 0 | 0 | 0 | $uri = $self->tweak_uri($uri) if $self->can('tweak_uri'); | |||
77 | |||||||
78 | 0 | 0 | $self->{uri} = $uri; # preserve for later use. | ||||
79 | |||||||
80 | 0 | 0 | return $uri; | ||||
81 | } | ||||||
82 | |||||||
83 | sub validator ($) { | ||||||
84 | 12 | 12 | 1 | 28 | my $hashref = shift; | ||
85 | 12 | 27 | my $pkg = caller; | ||||
86 | |||||||
87 | 12 | 20 | my %rules; | ||||
88 | 12 | 33 | foreach my $key ( keys %{ $hashref } ) { | ||||
12 | 45 | ||||||
89 | 24 | 39 | my $rule = $hashref->{$key}; | ||||
90 | 24 | 100 | 72 | if ( $rule eq 'is_number' ) { | |||
91 | $rules{$key} = sub { | ||||||
92 | 0 | 0 | 0 | my $value = shift; | |||
93 | 0 | 0 | 0 | 0 | $value && $value =~ /^\d+$/ ? 1 : 0; | ||
94 | 16 | 62 | }; | ||||
95 | } | ||||||
96 | 24 | 100 | 57 | if ( $rule eq 'is_number_or_all' ) { | |||
97 | $rules{$key} = sub { | ||||||
98 | 0 | 0 | 0 | my $value = shift; | |||
99 | 0 | 0 | 0 | 0 | $value && $value =~ /^(?:\d+|all)$/ ? 1 : 0; | ||
100 | 2 | 15 | }; | ||||
101 | } | ||||||
102 | 24 | 100 | 63 | if ( $rule eq 'is_anything' ) { | |||
103 | 3 | 0 | 15 | $rules{$key} = sub { 1 }; | |||
0 | 0 | ||||||
104 | } | ||||||
105 | } | ||||||
106 | |||||||
107 | 1 | 1 | 6 | no strict 'refs'; | |||
1 | 1 | ||||||
1 | 32 | ||||||
108 | 1 | 1 | 10 | no warnings 'redefine'; | |||
1 | 1 | ||||||
1 | 719 | ||||||
109 | 12 | 0 | 0 | 44 | *{"$pkg\::_is_valid"} = sub { return $rules{$_[1]} && $rules{$_[1]}->($_[2]) }; | ||
12 | 101 | ||||||
0 | |||||||
110 | } | ||||||
111 | |||||||
112 | sub post_process { | ||||||
113 | 0 | 0 | 1 | my ($self, $data, $callback) = @_; | |||
114 | |||||||
115 | 0 | my $arrayref = _force_arrayref($data); | |||||
116 | |||||||
117 | 0 | foreach my $item ( @{ $arrayref } ) { | |||||
0 | |||||||
118 | 0 | 0 | if ( ref $callback eq 'CODE' ) { | ||||
119 | 0 | $callback->($item); | |||||
120 | } | ||||||
121 | 0 | foreach my $key ( keys %{ $item } ) { | |||||
0 | |||||||
122 | 0 | 0 | next unless $item->{$key}; | ||||
123 | 0 | 0 | if ( $key =~ /time$/ ) { | ||||
0 | |||||||
0 | |||||||
124 | 0 | $item->{$key} = _datetime($item->{$key}) | |||||
125 | } | ||||||
126 | elsif ( $key =~ /(?:link|envelope|image|background|src|icon)$/ ) { | ||||||
127 | 0 | $item->{$key} = _uri($item->{$key}); | |||||
128 | } | ||||||
129 | elsif ( $key eq 'images' ) { | ||||||
130 | 0 | $item->{$key} = _images($item->{$key}); | |||||
131 | } | ||||||
132 | } | ||||||
133 | } | ||||||
134 | |||||||
135 | 0 | 0 | $arrayref = [ grep { %{ $_ } && !$_->{_delete} } @{ $arrayref } ]; | ||||
0 | |||||||
0 | |||||||
0 | |||||||
136 | |||||||
137 | 0 | return $arrayref; | |||||
138 | } | ||||||
139 | |||||||
140 | sub _images { | ||||||
141 | 0 | 0 | my $item = shift; | ||||
142 | |||||||
143 | 0 | 0 | $item = [ $item ] unless ref $item; # a thumbnail | ||||
144 | |||||||
145 | 0 | my @images; | |||||
146 | 0 | 0 | foreach my $i ( @{ $item || [] } ) { | ||||
0 | |||||||
147 | 0 | 0 | next unless $item; | ||||
148 | 0 | push @images, __images($i); | |||||
149 | } | ||||||
150 | 0 | return \@images; | |||||
151 | } | ||||||
152 | |||||||
153 | sub __images { | ||||||
154 | 0 | 0 | my $item = shift; | ||||
155 | 0 | my ($link, $thumb); | |||||
156 | 0 | 0 | unless ( ref $item eq 'HASH' ) { | ||||
157 | 0 | $link = $thumb = $item; | |||||
158 | 0 | $link =~ s/s\.jpg$/\.jpg/; | |||||
159 | 0 | $thumb =~ s/(?:[^s])\.jpg$/s\.jpg/; | |||||
160 | } | ||||||
161 | else { | ||||||
162 | 0 | 0 | $link = $item->{link} || ''; | ||||
163 | 0 | $thumb = $item->{thumb_link}; | |||||
164 | |||||||
165 | 0 | 0 | if ( $link =~ /MM_openBrWindow\(\s*'([^']+)'/ ) { $link = $1; } | ||||
0 | |||||||
166 | } | ||||||
167 | 0 | return { link => _uri($link), thumb_link => _uri($thumb) }; | |||||
168 | } | ||||||
169 | |||||||
170 | sub _extract_name { | ||||||
171 | 0 | 0 | my $item = shift; | ||||
172 | |||||||
173 | 0 | 0 | 0 | return unless defined $item->{string} && defined $item->{subject}; | |||
174 | |||||||
175 | 0 | my $name = substr( delete $item->{string}, length $item->{subject} ); | |||||
176 | 0 | $name =~ s/^\s*\(//; | |||||
177 | 0 | $name =~ s/\)\s*$//; | |||||
178 | 0 | $item->{name} = $name; | |||||
179 | } | ||||||
180 | |||||||
181 | 1; | ||||||
182 | |||||||
183 | __END__ |