Hello,
I have been away from Perl for about 10 years and I am trying to get back up to speed. The following script returns a "Not a HASH reference" error as shown in this printout from running the script (the script follow the ouput:
C:\Strawberry\perl\bin>C:\Strawberry\perl\bin\perl.exe "C:\Users\Bonni
+e\My Documents\alexa2.pl" http://www.gamegrene.com/
URI: http://data.alexa.com/data?cli=10&dat=snba&ver=7.0&url=http%3A%2F
+%2Fwww.gam
egrene.com%2F
Page: <?xml version="1.0" encoding="UTF-8"?>
<!-- Need more Alexa data? Find our APIs here: https://aws.amazon.com
+/alexa/ --
>
<ALEXA VER="0.9" URL="gamegrene.com/" HOME="0" AID="=" IDN="gamegrene.
+com/">
<RLS PREFIX="http://" more="0">
<RL HREF="www.gamereport.com/" TITLE="The Game Report Online"/>
<RL HREF="www.chimeramag.com/" TITLE="Chimera The Codependent Gaming M
+agazine"/>
<RL HREF="www.videounderbelly.com/wiki/Main_Page" TITLE="Main Page - V
+ideo Under
belly"/>
<RL HREF="www.ncbuy.com/" TITLE="Ncbuy"/>
<RL HREF="www.gnomestew.com/" TITLE="Gnome Stew, the Game Mastering Bl
+og"/>
<RL HREF="www.findwhitepapers.com/" TITLE="Find White Papers and Techn
+ology Rese
arch"/>
<RL HREF="www.disobey.com/" TITLE="Disobey: Content for the Discontent
+ed"/>
<RL HREF="www.3dgamers.com/" TITLE="3D Gamers"/>
<RL HREF="andreys.info/" TITLE="andrey's daily light and shadow |
+ photo blo
g | photography by"/>
<RL HREF="www.womengamers.com/" TITLE="Women Gamers"/>
</RLS>
<SD TITLE="A" FLAGS="" HOST="gamegrene.com">
<TITLE TEXT="Gamegrene"/>
<OWNER NAME="Disobey"/>
</SD>
<SD><POPULARITY URL="gamegrene.com/" TEXT="6678166" SOURCE="panel"/><R
+EACH RANK=
"5826716"/><RANK DELTA="-550802"/></SD></ALEXA>
XML: HASH(0x410f378)
XML: HASH(0x410f378)
Not a HASH reference at C:\Users\Bonnie\My Documents\alexa2.pl line 65
+ (#1)
(F) Perl was trying to evaluate a reference to a hash value, but f
+ound a
reference to something else instead. You can use the ref() functi
+on to
find out what kind of ref it really was. See perlref.
Uncaught exception from user code:
Not a HASH reference at C:\Users\Bonnie\My Documents\alexa2.pl
+ line 65.
main::handle_xml("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\x
+{d}\x{a}\x
{d}\x{a}<!-- Need more Alex"...) called at C:\Users\Bonnie\My Document
+s\alexa2.p
l line 83
C:\Strawberry\perl\bin>
#!/usr/bin/perl -w
use diagnostics;
use strict;
no strict qw(refs);
use URI;
use LWP::Simple;
use Net::Amazon;
use XML::Simple;
use constant AMAZON_TOKEN => 'amzn.mws.ccb04f71-d980-5fa6-0aed-b874a4b
+a9d58';
use constant DEBUG => 0;
# get our arguments. the first argument is the
# URL to fetch, and the second is the output.
my $url = shift || die "$0 <url> [<output>]\n";
my $output = shift || '/www/htdocs/cloud.html';
# we'll need to fetch the Alexa XML at some point, and
# we'll do it a few different times, so we create a
# subroutine for it. Using the URI module, we can
# correctly encode a URL with a query. In fact, you'll
# notice the majority of this function is involved with
# this, and at the end we use LWP::Simple to actually
# download and return the XML.
#####################################################
sub fetch_xml {
my $url = shift;
$url = "http://$url" unless $url =~ m[^http://];
warn "Fetching Alexa data for $url\n" if DEBUG;
my @args = (
cli => 10, dat => 'snba',
ver => '7.0', url => $url
);
my $base = 'http://data.alexa.com/data';
my $uri = URI->new( $base );
$uri->query_form( @args );
$uri = $uri->as_string;
print "\nURI: $uri\n";
return get( $uri );
}
# raw XML is no good for us, though, as we want to extract
# particular items of interest. we use XML::Simple to turn
# the XML into Perl data structures, because it's easier
# than fiddling with event handling (as with XML::Parser
# or XML::SAX), and we know there's only a small amount of
# data. we want the list of related sites and the list of
# related products. we extract and return both.
#####################################################
sub handle_xml {
my $page = shift;
print "\nPage: $page\n";
my $xml = XMLin( $page );
print "\nXML: $xml\n";
my @related = map {
{
asin => $_->{ASIN},
title => $_->{TITLE},
href => $xml->{RLS}{PREFIX}.$_->{HREF}
}
} @{ $xml->{RLS}{RL} };
print "\nXML: $xml\n";
print $xml->{SD}{AMZN}{PRODUCT};
my $refxml = (ref($xml->{SD}{AMZN}{PRODUCT}));
print $refxml;
my @products;
if (ref($xml->{SD}{AMZN}{PRODUCT}) eq "ARRAY") {
@products = map { $_->{ASIN} } @{ $xml->{SD}{AMZN}{PRODUCT} };
} else { @products = $xml->{SD}{AMZN}{PRODUCT}{ASIN}; }
return ( \@related, \@products );
}
# Functions done; now for the program:
warn "Start URL is $url\n" if DEBUG;
my @products; # running accumulation of product ASINs
{
my $page = fetch_xml( $url );
my ($related, $new_products) = handle_xml( $page );
@products = @$new_products; # running list
for (@$related) {
my $xml = fetch_xml( $_->{href} );
my ($related, $new_products) = handle_xml( $page );
push @products, @$new_products;
}
}
# We now have a list of products in @products, so
# we'd best do something with them. Let's look
# them up on Amazon and see what their titles are.
my $amazon = Net::Amazon->new( token => AMAZON_TOKEN );
my %products = map { $_ => undef } @products;
for my $asin ( sort keys %products ) {
warn "Searching for $asin...\n" if DEBUG;
my $response = $amazon->search( asin => $asin );
my @products = $response->properties;
die "ASIN is not unique!?" unless @products == 1;
my $product = $products[0];
$products{$asin} = {
name => $product->ProductName,
price => $product->OurPrice,
asin => $asin,
};
}
# Right. We now have name, price, and
# ASIN. Let's output an HTML report:
{
umask 022;
warn "Writing to $output\n" if DEBUG;
open my $fh, '>', $output or die $!;
print $fh "<html><head><title>Cloud around $url</title></head><bod
+y>";
if (keys %products) {
print $fh "<table>";
for my $asin (sort keys %products) {
my $data = $products{$asin};
printf $fh "<tr><td>".
"<a href=\"http://amazon.com/exec/obidos/ASIN/%
+s\">".
"%s</a></td> <td>%s</td></tr>",
@{$data}{qw( asin name price )};
}
print $fh "</table>";
}
else { print $fh "No related products found.\n"; }
print $fh "</body></html>\n";
}
The script is from the book "Spidering Hacks" and I wonder if I am running into problems as a result of changes in the Perl language from version 5.10 (when the book was written??) until today. I am using 5.30
Thank you for any and all insight on solving this.
Frank