tags:

views:

63

answers:

4

I can't seem to get these arrays to work. I'm getting errors along the following lines:

Global symbol '$href_array' requires specific package name

What does this mean? Here's part of my code:

sub scrape {
my ( $self, $DBhost, $DBuser, $DBpass, $DBname ) = @_;
my ($dbh, $query, $result, $array);
my $DNS = "dbi:mysql:$DBname:$DBhost:3306";
$dbh = DBI->connect($DNS, $DBuser, $DBpass ) or die $DBI::errstr;
if( defined( $self->{_process_image} ) && ( -e 'href_w_' . $self->{_process_image} . ".txt" ) ) {
    open  ERROR_W, "error_w_" . $self->{_process_image} . ".txt";
    open  M_HREF_W, "m_href_w_" . $self->{_process_image} . ".txt";
    open  HREF_W, "href_w_" . $self->{_process_image} . ".txt";
    my @m_error_array = ( split( '|||', <ERROR_W> ) );
    my @m_href_array = ( split( '|||', <M_HREF_W> ) );
    my @href_array = ( split( '|||', <HREF_W> ) );
    close ( ERROR_W );
    close ( M_HREF_W );
    close ( HREF_W );
}else{
    my @m_error_array;
    my @m_href_array;
    my @href_array = ( $self->{_url} );
}
my $z = 0;
while( $href_array ){
    if( defined( $self->{_x_more} ) && $z == $self->{_x_more} ) {
        break;
    }
    if( defined( $self->{_process_image} ) ) {
        $self->write( 'm_href_w', @m_href_array );
        $self->write( 'href_w', @href_array );
        $self->write( 'error_w', @m_error_array );
    }
    $self->{_link_count} = scalar @m_href_array;
}

}

FIXED:

#!/usr/bin/perl
use strict;
use URI;
use File::Basename;
use DBI;

package Crawler;
sub new {
    my $class = shift;
    my $self = {
        _url => shift,
        _max_link => 0,
        _local => 1
    };
    bless $self, $class;
    return $self;

}
sub process_image {
    my ($self, $process_image) = @_;
    $self->{_process_image} = $process_image;
}
sub local {
    my ($self, $local) = @_;
    $self->{_local} = $local;
}
sub max_link {
    my ($self, $max_link) = @_;
    $self->{_max_link} = $max_link;
}
sub x_more {
    my ($self, $x_more) = @_;
    $self->{_x_more} = $x_more;
}
sub resolve_href {
    my ($base, $href) = @_;
    my $uri = URI->new($href);
    return $uri->rel($base);    
}
sub write {
    my ( $self, $ref, $data ) = @_;
    open FILE, '>>' . $ref . '_' . $self->{_process_image} . '.txt';
    print FILE join( '|||', $data );
    close( FILE );
}
sub scrape {
    my @m_error_array;
    my @m_href_array;
    my @href_array;
    my ( $self, $DBhost, $DBuser, $DBpass, $DBname ) = @_;
    my ($dbh, $query, $result, $array);
    my $DNS = "dbi:mysql:$DBname:$DBhost:3306";
    $dbh = DBI->connect($DNS, $DBuser, $DBpass ) or die $DBI::errstr;
    if( defined( $self->{_process_image} ) && ( -e 'href_w_' . $self->{_process_image} . ".txt" ) ) {
        open  ERROR_W, "error_w_" . $self->{_process_image} . ".txt";
        open  M_HREF_W, "m_href_w_" . $self->{_process_image} . ".txt";
        open  HREF_W, "href_w_" . $self->{_process_image} . ".txt";
        my @m_error_array = ( split( '|||', <ERROR_W> ) );
        my @m_href_array = ( split( '|||', <M_HREF_W> ) );
        my @href_array = ( split( '|||', <HREF_W> ) );
        close ( ERROR_W );
        close ( M_HREF_W );
        close ( HREF_W );
    }else{
        @href_array = ( $self->{_url} );
    }
    my $z = 0;
    while( @href_array ){
        if( defined( $self->{_x_more} ) && $z == $self->{_x_more} ) {
            break;
        }
        if( defined( $self->{_process_image} ) ) {
            $self->write( 'm_href_w', @m_href_array );
            $self->write( 'href_w', @href_array );
            $self->write( 'error_w', @m_error_array );
        }
        $self->{_link_count} = scalar @m_href_array;
    }
}
1;

#$query = "SELECT * FROM `actwebdesigns.co.uk` ORDER BY ID DESC";
#$result = $dbh->prepare($query);
#$result->execute();
#while( $array = $result->fetchrow_hashref() ) {
#    print $array->{'URL'} . "\n";
#}
A: 

Your code includes while($href_array) but you don't declare a variable called $href_array.

You may have meant @href_array (these are not the same variable), although you don't seem to modify this array inside the loop.

Wooble
i get the same with `while(@href_array)`
Phil Jackson
+2  A: 

It means you are using an undeclared variable $href_array. You need to rewrite this line:

while( $href_array ){

to something like:

foreach my $element (@href_array) {

...although a bit more context is needed in this code to be able to understand what it is doing -- for example, you open a database connection in the scrape method ($dbh = ...), but never use it.

Ether
+2  A: 

Your code probably won't work the way you think it will. Take, for example, this block:

}else{
    my @m_error_array;
    my @m_href_array;
    my @href_array = ( $self->{_url} );
}

What this does is declare three arrays. That's all fine and good, but because you've used my, they "disappear" when they go out of scope at the end of the else{} block. You probably want to declare them up at the top, before your if...else block and remove the duplicated declarations from both blocks in the if...else section.

Then, you're probably trying to iterate over the @href_array list. You'll want to change your while() to something like:

foreach my $href_array ( @href_array ) {
    ...
}

All that said, kudos for putting use strict in your code (it must be there, or else you wouldn't have received the warning you did). That's an important thing that programmers new to Perl greatly benefit from, because it warns them about exactly this problem!

CanSpice
why am I not alowed to use break?
Phil Jackson
@Phil Jackson, in Perl, break is spelled `last`. (Actually, Perl 5.10 it's used with the new [`given`/`when` construct](http://perldoc.perl.org/perlsyn.html#Switch-statements).)
cjm
A: 

In all these answers no one bothers to tell you that the strict pragma enforces some more stringent coding practices in Perl. See its docs for the details. We explain it fully in Learning Perl too :)

When you get a warning you don't understand, you can get more information with the diagnostics. Here's an example:

use strict;
use diagnostics;

while( $href ) { 1 };

Here's the extended error message:

Execution of /Users/brian/Desktop/t aborted due to compilation errors (#1)
    (F) You've said "use strict" or "use strict vars", which indicates 
    that all variables must either be lexically scoped (using "my" or "state"), 
    declared beforehand using "our", or explicitly qualified to say 
    which package the global variable is in (using "::").
brian d foy
I actually did in my answer: "All that said, kudos for putting use strict in your code (it must be there, or else you wouldn't have received the warning you did). That's an important thing that programmers new to Perl greatly benefit from, because it warns them about exactly this problem!"
CanSpice
No, you just mentioned strict. You didn't explain what it was doing. You also buried it at the end because you got distracted by everything else going on. Always put the important stuff first.
brian d foy