I'm new to Mojolicious. I am sure this is probably a setup problem, but it's eaten up an entire day of my time. I'm trying to run this simple test code
#!/usr/bin/perl
use strict;
use warnings;
use Mojo::DOM;
use Mojo::UserAgent;
my $ua = Mojo::UserAgent->new();
$ua->get('https://stackoverflow.com/questions/26353298/find-links-containing-bold-text-using-wwwmechanize')->res->dom('a div')->ancestors('div.spacer')->each( sub { say $_->all_text } );
which I found at this location
find links containing bold text using WWW::Mechanize
and it is failing with
Can't locate object method "ancestors" via package "Mojo::Collection" at ./test4.pl line 10.
I've deinstalled and reinstalled a jillion times, tried different package installation options (cpan, cpanm, direct link, etc). No dice. I am mildly confused that the Mojo::Collection module does not appear to have an "ancestors" method in it (inherited or no), but I've seen several other examples like this which appear to use the same method in the same way. It's not just the "ancestors" module, either -- the problem seems to be affecting a few other methods as well.
I'm using perl 5.18.2 on Linux Mint with Mojolicious package 6.11.
Thanks for any help.
It's very difficult to debug a single long chained statement like that, and you're much better off splitting it into individual steps
Passing a parameter to the dom
method is the same as calling find
with that parameter on the DOM object. find
returns a Mojo::Collection
, which makes sense as it's the set of nodes that match the CSS selector. The ancestors
method applies only to a single node, so you have to pick one out with something like first
or last
, or process them all one at a time using each
Here's a rewrite of your code that produces what I assume is the expected result
use strict;
use warnings;
use 5.010;
use open qw/ :std :encoding(UTF-8) /;
use Mojo;
my $url = 'http://stackoverflow.com/q/26353298';
my $ua = Mojo::UserAgent->new->max_redirects(3);
my $dom = $ua->get($url)->res->dom;
my $divs = $dom->find('a div');
printf "%d matching div elements:\n\n", $divs->size;
my $n;
for my $div ( $divs->each ) {
my $spacers = $div->ancestors('div.spacer');
for my $spacer ( $spacers->each ) {
printf "%2d -- %s\n\n", ++$n, $spacer->all_text;
}
}
output
20 matching div elements:
1 -- Stack Exchange Podcast #65: The Word Has Two Meanings, You See
2 -- PIVOTing into a new career: please welcome Taryn Pratt, bluefooted Community …
3 -- 0 Can't locate module(s) using Mojo::DOM
4 -- 0 tiny runable www::Mechanize examples for the beginner
5 -- 2 Perl WWW::Mechanize and authenticated proxy
6 -- 0 How to process a simple loop in Perl's WWW::Mechanize?
7 -- 1 not able to click a button in www::mechanize perl
8 -- 0 Perl - Mechanize? - How to get all links in a page up to a specific “delimiter” text
9 -- 2 Why am I getting gibberish content using Perl's WWW::Mechanize?
10 -- 1 Getting error in accessing a link using WWW::Mechanize
11 -- 3 Perl WWW::Mechanize Web Spider. How to find all links
12 -- 0 What is the best way to extract unique URLs and related link text via perl mechanize?
13 -- 0 perl WWW::Mechanize file upload error