File Coverage

blib/lib/WWW/RSSFeed.pm
Criterion Covered Total %
statement 10 12 83.3
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 14 16 87.5


line stmt bran cond sub pod time code
1             package WWW::RSSFeed;
2              
3 1     1   23061 use 5.006;
  1         4  
  1         275  
4 1     1   8 use strict;
  1         2  
  1         43  
5 1     1   6 use warnings;
  1         7  
  1         49  
6 1     1   3463 use threads qw(stringify);
  0            
  0            
7             use threads::shared;
8             use WWW::Mechanize;
9             use Domain::PublicSuffix;
10             use XML::RSS;
11             use HTML::Summary;
12             use HTML::TreeBuilder;
13             use HTML::Scrubber;
14              
15             require Exporter;
16              
17             our @ISA = qw(Exporter);
18              
19             our %EXPORT_TAGS = ( 'all' => [ qw(
20             %feed_content_hr
21             ) ] );
22              
23             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
24              
25             our @EXPORT = qw(
26             getFeed
27             );
28              
29             our $VERSION = '0.01';
30             our %feed_content_hr : shared;
31              
32             =head1 NAME
33              
34             WWW::RSSFeed - Perl extension for creating RSS feeds from website(s).
35              
36             =head1 VERSION
37              
38             Version 0.01
39              
40             =head1 SYNOPSIS
41              
42             use strict;
43             use WWW::RSSFeed;
44              
45             my %input = (
46             'url' => 'http://www.yahoo.com/', # required
47             'max_items' => 100, #optional
48             'min_description_word_limit' => 50, #optional
49             );
50              
51             my $feedObj = new WWW::RSSFeed(\%input);
52             my $feedFile = $feedObj->getFeed();
53              
54             =head1 DESCRIPTION
55              
56             RSSFeed module can be used to create RSS feeds from website(s). This
57             module is provided as it is, the user is responsible if this module is used
58             to aggresively spider websites other than that of owner's. This activity may cause legal
59             obligations, so the user is hereby made aware. Use this on your own website.
60              
61             =head2 METHODS
62              
63             new() - The new subroutine.
64             getFeed() - Returns feed as a scalar.
65             __get_url_contents() - Returns global hash with title, link, description, links to other pages
66             in same domain and serial number. Increments global item count and
67             adds links to global hash.
68              
69             =head1 SEE ALSO
70              
71             This module is used at http://www.feedify.me/ ; a not for profit service from author
72             for webmasters.
73              
74             =head1 AUTHOR
75              
76             Kunal Jaiswal
77              
78             =head1 BUGS
79              
80             Please report any bugs or feature requests to C, or through
81             the web interface at L. I will be notified, and then you'll
82             automatically be notified of progress on your bug as I make changes.
83              
84              
85              
86              
87             =head1 SUPPORT
88              
89             You can find documentation for this module with the perldoc command.
90              
91             perldoc WWW::RSSFeed
92              
93              
94             You can also look for information at:
95              
96             =over 4
97              
98             =item * RT: CPAN's request tracker (report bugs here)
99              
100             L
101              
102             =item * AnnoCPAN: Annotated CPAN documentation
103              
104             L
105              
106             =item * CPAN Ratings
107              
108             L
109              
110             =item * Search CPAN
111              
112             L
113              
114             =back
115              
116             =head1 COPYRIGHT AND LICENSE
117              
118             Copyright (C) 2012 by Kunal Jaiswal
119              
120             This library is free software; you can redistribute it and/or modify
121             it under the same terms as Perl itself, either Perl version 5.12.4 or,
122             at your option, any later version of Perl 5 you may have available.
123              
124             =cut
125              
126             ######################################################################
127             ######################################################################
128             ####### #########
129             ####### new subroutine to define basic information. #########
130             ####### #########
131             ######################################################################
132             ######################################################################
133              
134             sub new{
135              
136             my ( $pkg, $input ) = @_;
137             my $obj = $input;
138             @_=();
139              
140             ## Set optional parameter if not supplied.
141             if(!$obj->{'max_items'}){
142             $obj->{'max_items'} = 20;
143             }
144              
145             if(!$obj->{'min_description_word_limit'}){
146             $obj->{'min_description_word_limit'} = 50;
147             }
148              
149             $feed_content_hr{'counter'} = 1;
150              
151             bless( $obj, ref($pkg) || $pkg );
152            
153             return $obj;
154             }
155              
156              
157             ######################################################################
158             ######################################################################
159             ####### #########
160             ####### Returns feed filename or feed as a scalar. #########
161             ####### #########
162             ######################################################################
163             ######################################################################
164              
165             sub getFeed{
166              
167             my ( $self ) = @_;
168             @_=();
169            
170             threads->create(\&__get_url_contents, $self)->join();
171            
172             return $self->__create_rss();
173             }
174              
175             ######################################################################
176             ######################################################################
177             ####### #########
178             ####### Returns global hash with title, link, description, #########
179             ####### links to other pages in same domain and serial #########
180             ####### number. Increments global item count and adds #########
181             ####### links to global hash. Only to be called with #########
182             ####### threads. #########
183             ####### #########
184             ######################################################################
185             ######################################################################
186              
187             sub __get_url_contents{
188              
189             my $self;
190              
191             ($self) = @_ if(@_);
192              
193             undef @_;
194              
195             if($feed_content_hr{$self->{'url'}}){ return ; }
196              
197             my $mech = WWW::Mechanize->new( timeout => 0.99 );
198             $mech->get($self->{'url'});
199              
200             my $tree = new HTML::TreeBuilder;
201             my $html_content = $mech->content();
202              
203             my $scrubber = HTML::Scrubber->new;
204              
205             $scrubber->default(1);
206             $scrubber->deny(qw[script style]);
207              
208             $html_content = $scrubber->scrub($html_content);
209              
210             $tree->parse( $html_content );
211             my $summarizer = new HTML::Summary(
212             LENGTH => 1500,
213             USE_META => 1,
214             );
215              
216             my $summary = $summarizer->generate($tree);
217              
218             $feed_content_hr{$self->{'url'}} = &share({});
219             $feed_content_hr{$self->{'url'}}{'title'} = $mech->title();
220             $feed_content_hr{$self->{'url'}}{'description'} = $summary;
221              
222             my $unwanted_files = 'css|js|jpg|jpeg|png|bmp|gif|tif|tiff|svg';
223             my @links = $mech->find_all_links( tag_regex => qr/^a$/,
224             url_regex => qr/[^$unwanted_files]$/);
225              
226             my $suffix = new Domain::PublicSuffix ({});
227              
228             @links = $self->__get_valid_links($suffix->get_root_domain($self->__root_domain($self->{'url'})), $suffix, @links);
229              
230             foreach my $link(@links){
231             if (($feed_content_hr{'counter'} < $self->{'max_items'}) && ($link)){
232             $self->{'url'} = $link;
233             $feed_content_hr{'counter'}++;
234             my $thread = threads->new(\&__get_url_contents, $self);
235             $thread->join();
236             }
237             }
238             }
239              
240             ######################################################################
241             ######################################################################
242             ####### #########
243             ####### Gives the root domain from a given url. #########
244             ####### #########
245             ######################################################################
246             ######################################################################
247              
248             sub __root_domain{
249              
250             my ( $self, $url ) = @_;
251             @_=();
252             $url =~ /([^:]*:\/\/)?([^\/]+)/g;
253             return $2;
254              
255             }
256              
257              
258             ######################################################################
259             ######################################################################
260             ####### #########
261             ####### Gives the root domain from a given url. #########
262             ####### #########
263             ######################################################################
264             ######################################################################
265              
266             sub __get_valid_links{
267              
268             my ( $self, $url, $suffix, @links ) = @_;
269             @_=();
270              
271             @links = map { $_ = $self->__get_inbound_links($url, $suffix, $_->url()); } @links;
272              
273             ##Send unique links
274             @links = keys %{{ map { $_ => 1 } @links }};
275             return @links;
276             }
277              
278             ######################################################################
279             ######################################################################
280             ####### #########
281             ####### Gives the root domain from a given url. #########
282             ####### #########
283             ######################################################################
284             ######################################################################
285              
286             sub __get_inbound_links{
287            
288             my ($self, $url, $suffix, $current_link) = @_;
289             @_=();
290              
291             if(($current_link =~ /^http/)
292             && ($suffix->get_root_domain($self->__root_domain($current_link)) ne $url)){
293             return '';
294             }
295              
296             if($current_link =~ /$url/){ return $current_link; }
297              
298             if($current_link !~ /^mailto:|javascript|\#/g){
299              
300             if($current_link !~ /^\//){ $current_link = '/'.$current_link; }
301             $current_link = "http://".$url.$current_link;
302              
303             }else{
304             $current_link = '';
305             }
306              
307             return $current_link;
308              
309             }
310              
311             ######################################################################
312             ######################################################################
313             ####### #########
314             ####### Gives the root domain from a given url. #########
315             ####### #########
316             ######################################################################
317             ######################################################################
318              
319             sub __create_rss{
320              
321             my ($self) = @_;
322             @_=();
323            
324             my $rss = XML::RSS->new (version => '2.0');
325              
326             foreach my $url(keys %feed_content_hr){
327              
328             if($url ne 'counter'){
329             $rss->add_item(title => $feed_content_hr{$url}{'title'},
330             link => $url,
331             description => $feed_content_hr{$url}{'description'});
332             }
333             }
334              
335              
336             return $rss->as_string;
337             }
338              
339             1; # End of WWW::RSSFeed
340             __END__