File Coverage

blib/lib/Email/Extractor/Utils.pm
Criterion Covered Total %
statement 102 106 96.2
branch 25 30 83.3
condition 4 6 66.6
subroutine 26 26 100.0
pod 13 13 100.0
total 170 181 93.9


line stmt bran cond sub pod time code
1             #ABSTRACT: Set of functions that can be useful when building web crawlers
2              
3              
4             package Email::Extractor::Utils;
5             $Email::Extractor::Utils::VERSION = '0.01';
6 2     2   58979 use strict;
  2         11  
  2         51  
7 2     2   7 use warnings;
  2         3  
  2         40  
8 2     2   7 use feature 'say';
  2         2  
  2         164  
9              
10 2     2   10 use Cwd;
  2         3  
  2         109  
11 2     2   9 use Carp;
  2         3  
  2         92  
12 2     2   804 use URI::URL;
  2         15030  
  2         77  
13 2     2   12 use File::Spec;
  2         4  
  2         46  
14 2     2   861 use File::Slurp qw(read_file);
  2         15284  
  2         96  
15 2     2   11 use File::Basename; # fileparse
  2         4  
  2         176  
16 2     2   872 use Regexp::Common qw /URI/;
  2         4551  
  2         6  
17 2     2   39459 use LWP::UserAgent;
  2         65227  
  2         84  
18 2     2   561 use Mojo::DOM;
  2         129542  
  2         2266  
19              
20             require Exporter;
21              
22             our @ISA = qw(Exporter);
23             our @EXPORT_OK = qw(
24             looks_like_url
25             looks_like_rel_link
26             looks_like_file
27             get_file_uri
28             load_addr_to_str
29             absolutize_links_array
30             find_all_links
31             find_links_by_text
32             drop_asset_links
33             drop_anchor_links
34             remove_query_params
35             remove_external_links
36             );
37             our %EXPORT_TAGS = ( 'ALL' => [@EXPORT_OK] );
38              
39             our $Verbose = 0 unless defined $Verbose;
40              
41              
42             our $Assets = [
43             'css', 'less', 'js', 'jpg', 'JPG', 'jpeg', 'JPEG', 'png',
44             'PNG', 'svg', 'doc', 'docx', 'ppt', 'odt', 'rtf', 'ppt'
45             ];
46              
47              
48             sub load_addr_to_str {
49 4     4 1 2034 my $addr = shift;
50              
51 4         9 eval {
52              
53 4 100       12 if ( looks_like_url($addr) ) {
54              
55 1 50       5 say "$addr: is url" if ($Verbose);
56 1         11 my $ua = LWP::UserAgent->new;
57 1         2761 my $resp = $ua->get($addr); # HTTP::Response
58 1         100 return $resp->content;
59              
60             }
61             else {
62              
63 3 50       9 say "$addr: is file" if ($Verbose);
64 3         6 my $file_uri = get_file_uri($addr);
65              
66 3 50       9 if ( looks_like_file($file_uri) ) {
67 3         7 return read_file( get_abs_path($addr) );
68              
69             }
70             else {
71 0         0 die "No such file: " . $addr . " or it is not file or http uri";
72             }
73              
74             }
75              
76             };
77             }
78              
79              
80             sub get_abs_path {
81 3     3 1 6 my $filename = shift;
82 3         54 return File::Spec->catfile( getcwd(), $filename );
83             }
84              
85              
86             sub get_file_uri {
87 3     3 1 6 my $filename = shift;
88 3         72 return 'file://' . File::Spec->catfile( getcwd(), $filename );
89             }
90              
91              
92             sub looks_like_url {
93 17     17 1 1080 my $string = shift;
94 17         91 my $regexp = qr($RE{URI}{HTTP}{-scheme=>qr/https?/}{-keep});
95 17 100       3079 if ( $string =~ $regexp ) {
96              
97             # warn "$1 $2 $3 $4 $5 $6 $7 $8";
98 9 100       43 return $7 if defined $7;
99 5 50       33 return $1 if defined $1;
100             }
101             else {
102 8         29 return 0;
103             }
104             }
105              
106              
107             sub looks_like_rel_link {
108 8     8 1 2373 my $link = shift;
109 8 100       12 return 0 if ( looks_like_url($link) );
110 4         10 return 1;
111             }
112              
113              
114             sub looks_like_file {
115 13     13 1 1988 my $string = shift;
116 13 100       52 if ( $string =~ qr($RE{URI}{file}) ) {
117 4         565 return 1;
118             }
119             else {
120 9         791 return 0;
121             }
122             }
123              
124              
125             sub absolutize_links_array {
126 3     3 1 3101 my ( $links_arr, $dname ) = @_;
127              
128 3 100 66     33 confess 'No valid dname in absolutize_links_array()'
129             unless defined $dname && length $dname;
130              
131 2         3 my @res;
132              
133 2         6 for my $l (@$links_arr) {
134 6 100       42 if ( looks_like_rel_link($l) ) {
135 3         13 $l = url( $l, $dname )->abs->as_string;
136             }
137 6         8619 push @res, $l;
138             }
139              
140 2         28 return \@res;
141             }
142              
143              
144             sub remove_external_links {
145 3     3 1 3087 my ( $links_arr, $only_dname ) = @_;
146              
147 3 100 66     28 confess 'No valid dname in remove_external_links()'
148             unless defined $only_dname && length $only_dname;
149              
150             my @res =
151 2 100       4 grep { ( $_ =~ /^$only_dname/ ) || looks_like_file( 'file://' . $_ ) }
  10         105  
152             @$links_arr;
153              
154             # looks_like_file('file://'.$_) = looks_like_relative_link
155 2         11 return \@res;
156             }
157              
158              
159             sub drop_asset_links {
160 7     7 1 2119 my $links = shift;
161              
162 7         12 $links = remove_query_params($links);
163              
164 7         12 my @res;
165              
166 7         11 for my $link (@$links) {
167 11         876 my ( $filename, $dirs, $suffix ) = fileparse( $link, @$Assets );
168 11 100       42 push( @res, $link ) if ( $suffix eq '' );
169             }
170              
171 7         24 return \@res;
172             }
173              
174              
175             sub drop_anchor_links {
176 7     7 1 2174 my $links_arr = shift;
177 7         12 my @res = grep { $_ !~ /^#/ } @$links_arr;
  8         26  
178 7         15 return \@res;
179             }
180              
181              
182             sub remove_query_params {
183 14     14 1 2053 my $links = shift;
184              
185 14         17 my @res;
186              
187 14         20 for my $link (@$links) {
188 22         45 my $uri = URI->new($link);
189 22 50       13691 if ( $uri->query ) {
190 0         0 my $l = length($link) - length( $uri->query ) - 1;
191 0         0 my $new_str = substr $link, 0, $l;
192 0         0 push( @res, $new_str );
193             }
194             else {
195 22         343 push( @res, $link );
196             }
197             }
198              
199 14         30 return \@res;
200             }
201              
202              
203             sub find_all_links {
204 7     7 1 2328 my $html = shift;
205 7         37 my $dom = Mojo::DOM->new($html);
206 7         1867 return $dom->find('a')->map( attr => 'href' )->to_array;
207             }
208              
209              
210             sub find_links_by_text {
211 10     10 1 4447 my ( $html, $a_text ) = @_;
212 10         33 my $dom = Mojo::DOM->new($html);
213              
214             # Mojo::Collection of Mojo::DOM
215             # return $dom->find('a')->grep('text' => $a_text)->map(attr => 'href')->to_array;
216 15     15   1778 return $dom->find('a')->grep( sub { $_->text eq $a_text } )
217 10         1869 ->map( attr => 'href' )->to_array;
218             }
219              
220             1;
221              
222             __END__