File Coverage

blib/lib/WWW/Find.pm
Criterion Covered Total %
statement 21 45 46.6
branch 0 6 0.0
condition 0 5 0.0
subroutine 7 13 53.8
pod 0 6 0.0
total 28 75 37.3


line stmt bran cond sub pod time code
1             package WWW::Find;
2              
3 1     1   26251 use 5.006;
  1         4  
  1         36  
4 1     1   6 use strict;
  1         1  
  1         34  
5 1     1   4 use warnings;
  1         7  
  1         41  
6 1     1   5 use Carp;
  1         2  
  1         99  
7 1     1   1055 use URI;
  1         12653  
  1         44  
8 1     1   1065 use URI::Heuristic;
  1         2819  
  1         60  
9 1     1   897 use HTML::LinkExtor;
  1         11838  
  1         806  
10              
11             our $VERSION = '0.07';
12             my $depth = 0;
13             my %seen;
14              
15             # Default URL matching subroutine
16             sub match_sub {
17 0     0 0   my($self) = shift;
18              
19             ## tests for URL's matching this REGEX
20 0 0         if($self->{REQUEST}->uri =~ /html?$/io) {
21              
22             ## do something with matching URL's
23             ## print to STDOUT is the default action
24 0           print $self->{REQUEST}->uri . "\n";
25             }
26             return
27 0           }
28              
29             ## Default URL follow subtroutine
30             ## Should return true or false
31             sub follow_sub {
32 0     0 0   my $self = shift;
33 0           my $header = HTTP::Request->new(HEAD => $self->{REQUEST}->uri);
34 0   0       my $response = $self->{AGENT}->request($header) || next;
35 0 0 0       $response->content_type eq 'text/html' && ref($self->{REQUEST}->uri) eq 'URI::http'
36             ? return 1
37             : return 0
38             }
39              
40             ## Private methods
41              
42             my $_rec;
43             $_rec = sub {
44             my $find_obj = shift;
45             my $uri = URI->new($find_obj->{REQUEST}->uri);
46             # $seen{$uri}++;
47             # return if($seen{$uri} > 1);
48             return if($depth > $find_obj->{MAX_DEPTH});
49             $depth++;
50              
51             ## Request HTML Document
52             my $html = $find_obj->{AGENT}->request($find_obj->{REQUEST});
53              
54             ## Parse out HREF links
55             my $parser = HTML::LinkExtor->new(undef);
56             $parser->parse($html->content);
57             my @links = $parser->links;
58             foreach my $ln (@links)
59             {
60             my @element = @$ln;
61             my $type = shift @element;
62             next unless($type =~ /^a/io);
63             while(@element)
64             {
65             my ($name, $value) = splice(@element, 0, 2);
66              
67             ## Make URL absolute
68             $find_obj->{REQUEST}->uri(URI->new_abs($value, $uri));
69             my $url = $find_obj->{REQUEST}->uri;
70              
71             ## Check recursion depth
72             next if($depth > $find_obj->{MAX_DEPTH});
73              
74             ## Skip if duplicate
75             $seen{$url}++;
76             next if($seen{$url} > 1);
77             ## User defined matching subroutine
78             $find_obj->{MATCH_SUB}($find_obj);
79              
80             ## Check recursion depth
81             # next if($depth > $find_obj->{MAX_DEPTH});
82              
83             ## Modify request object for next request
84             if(ref($find_obj->{REQUEST}->uri))
85             {
86             $find_obj->{REQUEST}->uri(URI::Heuristic::uf_urlstr($find_obj->{REQUEST}->uri));
87              
88             ## User defined follow subroutine
89             &$_rec($find_obj) if ($find_obj->{FOLLOW_SUB}($find_obj));
90             }
91             }
92             }
93             $depth--;
94              
95             };
96              
97             # constructor
98             sub new
99             {
100 0     0 0   my($class, %parm) = @_;
101 0 0         croak 'Expecting a class' if ref $class;
102 0           my $self = { MAX_DEPTH => 2,
103             DIRECTORY => '.',
104             MATCH_SUB => \&match_sub,
105             FOLLOW_SUB => \&follow_sub
106             };
107             ## Parms should be validated, but I'm feeling lazy
108 0           while(my($k, $v) = each(%parm)) { $self->{$k} = $v};
  0            
109 0           bless $self, $class;
110 0           return $self;
111             }
112              
113             ## Public methods
114             sub go {
115 0     0 0   my($self, %parm) = @_;
116 0           $self->{REQUEST}->uri(URI::Heuristic::uf_urlstr($self->{REQUEST}->uri));
117 0           &$_rec($self);
118             }
119              
120             sub set_match {
121 0     0 0   my($self, $sub_ref) = @_;
122 0           $self->{MATCH_SUB} = $sub_ref;
123 0           return $self->{MATCH_SUB};
124             }
125              
126             sub set_follow {
127 0     0 0   my($self, $sub_ref) = @_;
128 0           $self->{FOLLOW_SUB} = $sub_ref;
129 0           return $self->{FOLLOW_SUB};
130             }
131              
132             1;
133              
134             __END__