File Coverage

blib/lib/URI/ParseSearchString/More.pm
Criterion Covered Total %
statement 119 136 87.5
branch 20 32 62.5
condition 1 6 16.6
subroutine 21 23 91.3
pod 8 8 100.0
total 169 205 82.4


line stmt bran cond sub pod time code
1 4     4   662485 use warnings;
  4         29  
  4         100  
2 4     4   16 use strict;
  4         5  
  4         144  
3              
4             package URI::ParseSearchString::More;
5             our $VERSION = '0.18';
6 4     4   21 use base qw( URI::ParseSearchString );
  4         7  
  4         1929  
7              
8 4     4   30297 use List::Compare ();
  4         59462  
  4         81  
9 4     4   1393 use LWP::Protocol::https ();
  4         334375  
  4         158  
10 4     4   1609 use Params::Validate qw( validate SCALAR );
  4         19609  
  4         233  
11 4     4   23 use Try::Tiny qw( catch try );
  4         9  
  4         151  
12 4     4   17 use URI ();
  4         6  
  4         54  
13 4     4   1406 use URI::Heuristic qw(uf_uristr);
  4         5101  
  4         165  
14 4     4   1211 use URI::QueryParam ();
  4         2229  
  4         64  
15 4     4   1422 use WWW::Mechanize::Cached ();
  4         437963  
  4         5093  
16              
17             my %search_regex = (
18             answers => [qr{(.*)}],
19             aol => [qr{(.*) - AOL Search Results}],
20             as => [qr{Starware (.*) Search Results}],
21             dogpile => [qr{(.*) - Dogpile Web Search}],
22             );
23              
24             my %url_regex = (
25             answers => qr{answers.yahoo.com},
26             aol => qr{aol.com/(?:aol|aolcom)/search\?encquery=},
27             as => qr{as.\w+.com/dp/search\?x=},
28             dogpile => qr{http://www.dogpile},
29             );
30              
31             # local.yahoo.com should come before Yahoo as it has different
32             # params
33             # ie. this list is for ordering some of the engines in the regex. if an
34             # engine has no reason to be at a certain point in the list, it should
35             # just be listed in the %query_lookup table
36              
37             my @engines = (
38             'local.google', 'maps.google',
39             'googlesyndication', 'google',
40             'local.yahoo.com', 'search.yahoo.com',
41             'shopping.yahoo.com', 'yahoo',
42             'alltheweb.com', 'errors.aol.com',
43             'sucheaol.aol.de', 'aol',
44             'ask.*', 'fastbrowsersearch.com',
45             'as.*.com', 'att.net',
46             'trustedsearch.com',
47             );
48              
49             my %query_lookup = (
50              
51             'abcsok.no' => ['q'],
52             'about.com' => ['terms'],
53             'alltheweb.com' => ['q'],
54             'answers.com' => ['s'],
55             'aol' => [ 'query', 'q' ],
56             'as.*.com' => ['qry'],
57             'ask.*' => ['q'],
58             'att.net' => [ 'qry', 'q' ],
59             'baidu.com' => ['bs'],
60             'bing.com' => ['q'],
61             'blingo.com' => ['q'],
62             'citysearch.com' => ['query'],
63             'clicknow.org.uk' => ['q'],
64             'clusty.com' => ['query'],
65             'comcast.net' => [ 'query', 'q' ],
66             'cuil.com' => ['q'],
67             'danielsearch.info' => ['q'],
68             'devilfinder.com' => ['q'],
69             'ebay' => ['satitle'],
70             'education.yahoo.com' => ['p'],
71             'errors.aol.com' => ['host'],
72             'excite' => ['search'],
73             'ez4search.com' => ['searchname'],
74             'fastbrowsersearch.com' => ['q'],
75             'fedstats.com' => ['s'],
76             'find.copernic.com' => ['query'],
77             'finna.is' => ['query'],
78             'googlesyndication' => [ 'q', 'ref', 'loc' ],
79             'google' => [ 'q', 'as_q' ],
80             'googel' => ['q'],
81             'hotbot.lycos.com' => ['query'],
82             'isearch.com' => ['Terms'],
83             'local.google' => [ 'q', 'near' ],
84             'local.yahoo.com' => [ 'stx', 'csz' ],
85             'looksmart.com' => ['key'],
86             'lycos' => ['query'],
87             'maps.google' => [ 'q', 'near' ],
88             'msntv.msn.com' => ['q'],
89             'munky.com' => ['term'],
90             'mysearch.com' => ['searchfor'],
91             'mywebsearch.com' => ['searchfor'],
92             'mytelus.com' => ['q'],
93             'netscape.com' => ['query'],
94             'nextag.com' => ['search'],
95             'overture.com' => ['Keywords'],
96             'pricescan.com' => ['SearchString'],
97             'reviews.search.com' => ['q'],
98             'search.com' => ['q'],
99             'searchalot.com' => ['q'],
100             'searchfusion.com' => ['t'],
101             'searchon.ca' => ['Terms'],
102             'search.cnn.com' => ['query'],
103             'search.bearshare.com' => ['q'],
104             'search.comcast.net' => ['q'],
105             'search.dmoz.org' => ['search'],
106             'search.earthlink.net' => ['q'],
107             'search.findsall.info' => ['s'],
108             'search.freeserve.com' => ['q'],
109             'search.freeze.com' => ['Keywords'],
110             'search.go.com' => ['search'],
111             qr/search\d?.incredimail.com/ => ['q'],
112             'search.juno.com' => ['query'],
113             'search.iol.ie' => ['q'],
114             'search.live.com' => ['q'],
115             'search.netzero.net' => ['query'],
116             'search.*.msn.' => ['q'],
117             'search.myway.com' => ['searchfor'],
118             'search.opera.com' => ['search'],
119             'search.rogers.com' => [ 'qf', 'qo' ],
120             'search.rr.com' => ['qs'],
121             'search.start.co.il' => ['q'],
122             'search.starware.com' => ['qry'],
123             'search.sympatico.msn.ca' => ['q'],
124             'search.sweetim.com' => ['q'],
125             'search.usatoday.com' => ['kw'],
126             'search.virgilio.it' => ['qs'],
127             'search.wanadoo.co.uk' => ['q'],
128             'search.yahoo.com' => [ 'q', 'va', 'p' ],
129             'searchservice.myspace.com' => ['qry'],
130             'shopping.yahoo.com' => ['p'],
131             'start.shaw.ca' => ['q'],
132             'startgoogle.startpagina.nl' => ['q'],
133             'stumbleupon.com' => ['url'],
134             'sucheaol.aol.de' => ['q'],
135             'teoma.com' => ['q'],
136             'toronto.com' => ['query'],
137             'trustedsearch.net' => ['w'],
138             'trustedsearch.com' => ['w'],
139             'yahoo' => ['p'],
140             'yandex.ru' => ['text'],
141             'youtube.com' => ['search_query'],
142             'websearch.cbc.ca' => ['query'],
143             'websearch.cs.com' => ['query'],
144             'webtv.net' => ['q'],
145             'www.bestsearchonearth.info' => ['Keywords'],
146             'www.boat.com' => ['HotKeysTopCategory'],
147             'www.factbites.com' => ['kp'],
148             'www.mweb.co.za' => ['q'],
149             'www.rr.com/html/search.cfm' => ['query'],
150             'www.wotbox.com' => ['q'],
151             );
152              
153             sub parse_search_string {
154 136     136 1 324174 my $self = shift;
155 136         201 my $url = shift;
156              
157 136         322 foreach my $engine ( keys %url_regex ) {
158              
159 543 100       1614 if ( $url =~ $url_regex{$engine} ) {
160              
161             # fix funky URLs
162 1         6 $url = uf_uristr($url);
163              
164 1         30 my $mech = $self->get_mech();
165              
166 1     1   81 try { $mech->get($url); }
167             catch {
168 0     0   0 warn "Issue with url: $url";
169 0         0 warn $_;
170 1         12 };
171              
172 1 50 33     955261 if ( $mech->status && $mech->status == 403 ) {
173 0         0 warn "403 returned for $url Are you being blocked?";
174             }
175              
176 1 50       18 if ( $mech->title() ) {
177 1         1562 my $search_term = $self->_apply_regex(
178             string => $mech->title(),
179             engine => $engine,
180             );
181              
182 1 50       3 if ($search_term) {
183 1         4 $self->{'more'}->{'blame'} = __PACKAGE__;
184 1         6 return $search_term;
185             }
186             }
187             }
188             }
189              
190 135         274 my $terms = $self->parse_more($url);
191              
192 135 50       237 if ($terms) {
193 135         311 $self->{'more'}->{'blame'} = __PACKAGE__;
194 135         285 return $terms;
195             }
196              
197             # We've come up empty. Let's see what the superclass can do
198 0         0 $self->{'more'}->{'blame'} = 'URI::ParseSearchString';
199 0         0 return $self->SUPER::parse_search_string( $url, @_ );
200             }
201              
202             sub se_term {
203 1     1 1 1271 my $self = shift;
204 1         4 return $self->parse_search_string(@_);
205             }
206              
207             sub parse_more {
208 135     135 1 158 my $self = shift;
209 135         161 my $url = shift;
210              
211 135 50       209 die 'you need to supply at least one argument' unless $url;
212              
213 135         426 $self->{'more'} = undef;
214 135         262 $self->{'more'}->{'string'} = $url;
215              
216 135         212 my $regex = join ' | ', $self->_get_engines;
217 135         548 $self->{'more'}->{'regex'} = $regex;
218 135         193 $self->{'more'}->{'url'} = $url;
219              
220 135 50       2610 if ( $url =~ m{ ( (?: $regex ) .* ?/ ) .* ?\? (.*)\z }xms ) {
221              
222 135         351 my $domain = $1;
223              
224             # remove trailing slash
225 135         402 $domain =~ s{/\z}{};
226              
227 135         210 my @param_parts = ();
228 135         161 my %params = ();
229              
230 135         328 my $uri = URI->new($url);
231              
232             ENGINE:
233 135         23599 foreach my $engine ( $self->_get_engines ) {
234              
235 5531 100       24137 if ( $domain =~ /$engine/i ) {
236              
237 135         192 my @names = @{ $query_lookup{$engine} };
  135         354  
238              
239 135         270 $self->{'more'}->{'domain'} = $domain;
240 135         285 $self->{'more'}->{'names'} = \@names;
241              
242 135         203 foreach my $name (@names) {
243 170         3439 push @param_parts, $uri->query_param($name);
244 170         14895 $params{$name} = $uri->query_param($name);
245             }
246              
247 135         10441 last ENGINE;
248             }
249             }
250              
251 135         692 my $params = join( q{ }, @param_parts );
252 135         174 my $orig_domain = $domain;
253 135         191 $domain =~ s/\/.*//g;
254 135 50       344 unless ( $domain =~ /\w/ ) {
255 0         0 $domain = $orig_domain;
256             }
257              
258 135         231 $self->{'more'}->{'terms'} = \@param_parts;
259 135         179 $self->{'more'}->{'params'} = \%params;
260              
261 135         455 return $params;
262             }
263              
264 0         0 return;
265             }
266              
267             sub blame {
268 134     134 1 179 my $self = shift;
269 134         347 return $self->{more}->{blame};
270             }
271              
272             sub guess {
273 0     0 1 0 my $self = shift;
274 0   0     0 my $url = shift || $self->{'more'}->{'string'};
275              
276 0         0 my @guesses = ( 'q', 'query', 'searchfor' );
277              
278 0         0 my $uri = URI->new($url);
279 0 0       0 if ( $uri->query_params ) {
280              
281 0         0 foreach my $guess (@guesses) {
282 0 0       0 if ( $uri->query_param($guess) ) {
283 0         0 return $uri->query_param($guess);
284             }
285             }
286             }
287              
288 0         0 return;
289             }
290              
291             sub set_cached {
292 3     3 1 11573 my $self = shift;
293 3         6 my $switch = shift;
294              
295 3 100       6 if ($switch) {
296 1         3 $self->{'__more_cached'} = 1;
297             }
298             else {
299 2         5 $self->{'__more_cached'} = 0;
300             }
301              
302 3         4 return $self->{'__more_cached'};
303             }
304              
305             sub get_cached {
306 276     276 1 278 my $self = shift;
307              
308 276         348 return $self->{'__more_cached'};
309             }
310              
311             sub get_mech {
312 274     274 1 585 my $self = shift;
313 274         378 my $cache = $self->get_cached;
314              
315 274 100       379 if ($cache) {
316              
317 2 100       4 if ( !exists $self->{'__more_mech_cached'} ) {
318              
319 1         10 my $mech = WWW::Mechanize::Cached->new();
320 1         3932 $mech->agent('URI::ParseSearchString::More');
321 1         48 $self->{'__more_mech_cached'} = $mech;
322              
323             }
324              
325 2         8 return $self->{'__more_mech_cached'};
326              
327             }
328              
329             # return a non-caching object
330 272 100       356 if ( !exists $self->{'__more_mech'} ) {
331              
332 2         13 my $mech = WWW::Mechanize->new();
333 2         11345 $mech->agent('URI::ParseSearchString::More');
334 2         120 $self->{'__more_mech'} = $mech;
335              
336             }
337              
338 272         518 return $self->{'__more_mech'};
339             }
340              
341             sub _apply_regex {
342 2     2   1996934 my $self = shift;
343 2         26 my %rules = (
344             string => { type => SCALAR },
345             engine => { type => SCALAR },
346             );
347              
348 2         56 my %args = validate( @_, \%rules );
349              
350 2         9 foreach my $regex ( @{ $search_regex{ $args{'engine'} } } ) {
  2         11  
351 2 50       21 if ( $args{'string'} =~ $regex ) {
352 2         15 return $1;
353             }
354             }
355 0         0 return;
356             }
357              
358             sub _get_engines {
359 271     271   4268 my $lc = List::Compare->new( \@engines, [ keys %query_lookup ] );
360 271         152896 my @remaining_engines = $lc->get_complement;
361              
362 271         4057 my @all_engines = @engines;
363 271         1456 push @all_engines, @remaining_engines;
364              
365 271         6987 return @all_engines;
366             }
367              
368             1;
369              
370             # ABSTRACT: Extract search strings from more referrers.
371              
372             __END__