File Coverage

blib/lib/HTML/ExtractText.pm
Criterion Covered Total %
statement 85 86 98.8
branch 28 32 87.5
condition 12 15 80.0
subroutine 19 20 95.0
pod 7 7 100.0
total 151 160 94.3


line stmt bran cond sub pod time code
1             package HTML::ExtractText;
2              
3 4     4   134646 use strict;
  4         9  
  4         120  
4 4     4   15 use warnings;
  4         5  
  4         137  
5              
6             our $VERSION = '1.002002'; # VERSION
7              
8 4     4   1432 use Try::Tiny;
  4         3346  
  4         192  
9 4     4   20 use Scalar::Util qw/blessed/;
  4         17  
  4         151  
10 4     4   19 use Carp qw/croak/;
  4         5  
  4         126  
11 4     4   1313 use Devel::TakeHashArgs;
  4         1091  
  4         218  
12 4     4   1440 use Mojo::DOM;
  4         158964  
  4         214  
13 0     0   0 use overload q|""| => sub { shift->error },
14 4     4   28 q|%{}| => sub { shift->last_results };
  4     6   6  
  4         41  
  6         31694  
15              
16             sub new {
17 12     12 1 5636 my $self = bless [], shift;
18 12 50       72 get_args_as_hash( \@_, \ my %args,
19             { # these are optional with defaults
20             separator => "\n",
21             ignore_not_found => 1,
22             },
23             [ ], # these are mandatory (none, ATM)
24             [ qw/separator ignore_not_found/ ], # only these args are valid ones
25             ) or croak $@;
26              
27 12         328 $self->$_( $args{$_} ) for keys %args;
28              
29 12         32 return $self;
30             }
31              
32             sub extract {
33 10     10 1 1275 my ( $self, $what, $html, $obj ) = @_;
34              
35 10         23 $self->error( undef );
36 10         14 $self->last_results( undef );
37              
38 10 50       23 ref $what eq 'HASH'
39             or return $self->_set_error('First argument to '
40             . 'extract_text() must be a hashref');
41              
42 10 50       22 defined $html
43             or return $self->_set_error('Second argument to extract_text() is '
44             . 'an undef, expected HTML');
45              
46 10 100       18 if ( defined $obj ) {
47 3 100       13 blessed $obj
48             or return $self->_set_error('Third argument must be an object');
49              
50 2         5 for ( keys %$what ) {
51 2 100       18 $obj->can($_)
52             or return $self->_set_error(
53             'The object your provided does not implement the ->'
54             . $_ . '() method that you requested in the first'
55             . ' argument',
56             );
57             }
58             }
59              
60              
61 8         37 my $dom = Mojo::DOM->new( $html );
62              
63 8         3046 my $did_have_error = 0;
64 8         38 for my $selector ( sort keys %$what ) {
65 22         20 my $result;
66              
67             try {
68             my @results
69             = $dom->find( $what->{ $selector } )->map(sub{
70 29         6748 my $tag = $_->tag;
71 29 100       365 return $_->all_text unless $tag =~ /input|img/;
72              
73 7 100 100     33 return $_->attr('alt')//''
      100        
      66        
      66        
74             if $tag eq 'img' or
75             ($tag eq 'input' and ($_->attr('type')//'') eq 'image');
76              
77 4   100     57 return $_->attr('value')//'';
78 22     22   527 })->each;
79              
80 22         1484 $self->extra_processing( \@results, $dom, $selector, $what );
81              
82 22 50 66     54 die "NOT FOUND\n"
83             if not @results and not $self->ignore_not_found;
84              
85 21 100       34 if ( defined (my $sep = $self->separator) ) {
86 9         28 $result = join $sep, @results;
87             }
88             else {
89 12         36 $result = [ @results ];
90             }
91              
92             } catch {
93 1     1   8 chomp($_);
94 1         3 $self->error("ERROR: [$selector]: $_");
95 1         1 $result = "ERROR: $_";
96 1         4 $did_have_error = 1;
97 22         136 };
98              
99 22         277 $what->{ $selector } = $result;
100             }
101              
102 8 100       18 if ( defined $obj ) {
103 1         3 for ( keys %$what ) {
104 1         4 $obj->$_( $what->{ $_ } );
105             }
106             }
107              
108 8         22 $self->last_results( $what );
109              
110 8 100       14 if ( $did_have_error ) {
111 1         6 return;
112             }
113             else {
114 7         44 return $what;
115             }
116             }
117              
118             sub separator {
119 37     37 1 37 my $self = shift;
120 37 100       68 if ( @_ ) { $self->[0]->{SEPARATOR} = shift; }
  14         95  
121 37         99 return $self->[0]->{SEPARATOR};
122             }
123              
124             sub ignore_not_found {
125 15     15 1 18 my $self = shift;
126 15 100       29 if ( @_ ) { $self->[0]->{IGNORE_NOT_FOUND} = shift; }
  13         52  
127 15         39 return $self->[0]->{IGNORE_NOT_FOUND};
128             }
129              
130             sub last_results {
131 30     30 1 40 my $self = shift;
132 30 100       54 if ( @_ ) { $self->[0]->{LAST_RESULTS} = shift; }
  18         23  
133 30         89 return $self->[0]->{LAST_RESULTS};
134             }
135              
136             sub error {
137 16     16 1 234 my $self = shift;
138 16 100       31 if ( @_ ) { $self->[0]->{ERROR} = shift; }
  13         21  
139 16         29 return $self->[0]->{ERROR};
140             }
141              
142             sub _set_error {
143 2     2   3 my ( $self, $error ) = @_;
144 2         7 $self->error( $error );
145 2         7 return;
146             }
147              
148 21     21 1 22 sub extra_processing {
149             # this is for overriding in subclasses
150             }
151              
152              
153              
154             q|
155             Programming is 10% science, 20% ingenuity,
156             and 70% getting the ingenuity to work with the science.
157             |;
158              
159             __END__