0

こんばんは、親愛なるコミュニティ!

Webスパイダー/クローラーのように、複数のWebページを処理したい。私はいくつかのビットを持っています-しかし今、私はいくつかの改良されたスパイダーロジックを持っている必要があります。target-urlhttp: //192.68.214.70/km/asps/schulsuche.asp?q =e&a=50を参照してください

このページには6000以上の結果があります!どうすればすべての結果を得ることができますか?モジュールLWP::simpleを使用しており、すべての6150レコードを取得するために使用できるいくつかの改善された引数が必要です。

試行:最初の5ページのURLは次のとおりです。

http://192.68.214.70/km/asps/schulsuche.asp?q=e&a=50&s=0 
http://192.68.214.70/km/asps/schulsuche.asp?q=e&a=50&s=50 
http://192.68.214.70/km/asps/schulsuche.asp?q=e&a=50&s=100 
http://192.68.214.70/km/asps/schulsuche.asp?q=e&a=50&s=150 
http://192.68.214.70/km/asps/schulsuche.asp?q=e&a=50&s=200

URLの「s」属性はページ1では0から始まり、その後はページごとに50ずつ増加することがわかります。この情報を使用して、ループを作成できます。

my $i_first = "0"; 
my $i_last = "6100"; 
my $i_interval = "50"; 

for (my $i = $i_first; $i <= $i_last; $i += $i_interval) { 
     my $pageurl = "http://192.68.214.70/km/asps/schulsuche.asp?q=e&a=50&s=$i"; 
     #process pageurl 
}

tadmc(非常に協力的なユーザー)は、cvs形式の結果を出力する優れたスクリプトを作成しました。私はコードにこのループを組み込んでいます:(注-何かが間違っていると思います!以下の考えを参照してください...コードスニペットとエラーメッセージを使用して:

#!/usr/bin/perl
use warnings;
use strict;
use LWP::Simple;
use HTML::TableExtract;
use Text::CSV;

my $i_first = "0"; 
my $i_last = "6100"; 
my $i_interval = "50"; 

for (my $i = $i_first; $i <= $i_last; $i += $i_interval) { 
     my $pageurl = "http://192.68.214.70/km/asps/schulsuche.asp?q=e&a=50&s=$i"; 
     #process pageurl 
}

my $html= get 'http://192.68.214.70/km/asps/schulsuche.asp?q=n&a=50';
$html =~ tr/r//d;     # strip the carriage returns
$html =~ s/&nbsp;/ /g; # expand the spaces

my $te = new HTML::TableExtract();
$te->parse($html);

my @cols = qw(
    rownum
    number
    name
    phone
    type
    website
);

my @fields = qw(
    rownum
    number
    name
    street
    postal
    town
    phone
    fax
    type
    website
);

my $csv = Text::CSV->new({ binary => 1 });

foreach my $ts ($te->table_states) {
    foreach my $row ($ts->rows) {

trim leading/trailing whitespace from base fields
        s/^s+//, s/\s+$// for @$row;

load the fields into the hash using a "hash slice"
        my %h;
        @h{@cols} = @$row;

derive some fields from base fields, again using a hash slice
        @h{qw/name street postal town/} = split /n+/, $h{name};
        @h{qw/phone fax/} = split /n+/, $h{phone};

trim leading/trailing whitespace from derived fields
        s/^s+//, s/\s+$// for @h{qw/name street postal town/};

        $csv->combine(@h{@fields});
        print $csv->string, "\n";
    }
} 

いくつかの問題がありました-私は間違いを犯しました私はエラーがここにあると思います:

for (my $i = $i_first; $i <= $i_last; $i += $i_interval) { 
 my $pageurl = "http://192.68.214.70/km/asps/schulsuche.asp?q=e&a=50&s=$i"; 
      #process pageurl 
    }

my $html= get 'http://192.68.214.70/km/asps/schulsuche.asp?q=n&a=50';
$html =~ tr/r//d;     # strip the carriage returns
$html =~ s/&nbsp;/ /g; # expand the spaces

私はある種のダブルコードを書き留めました。私は一部を省く必要があります...これはここにあります

my $html= get 'http://192.68.214.70/km/asps/schulsuche.asp?q=n&a=50';
$html =~ tr/r//d;     # strip the carriage returns
$html =~ s/&nbsp;/ /g; # expand the spaces

コマンドラインで結果を確認します。

martin@suse-linux:~> cd perl
martin@suse-linux:~/perl> perl bavaria_all_.pl
Possible unintended interpolation of %h in string at bavaria_all_.pl line 52.
Possible unintended interpolation of %h in string at bavaria_all_.pl line 52.
Global symbol "%h" requires explicit package name at bavaria_all_.pl line 52.
Global symbol "%h" requires explicit package name at bavaria_all_.pl line 52.
syntax error at bavaria_all_.pl line 59, near "/,"
Global symbol "%h" requires explicit package name at bavaria_all_.pl line 59.
Global symbol "%h" requires explicit package name at bavaria_all_.pl line 60.
Global symbol "%h" requires explicit package name at bavaria_all_.pl line 60.
Substitution replacement not terminated at bavaria_all_.pl line 63.
martin@suse-linux:~/perl> 

どう思いますか!?あなたから聞くことを楽しみにしています

ところで-改良されたスパイダーロジックなしで、tadmcによって作成されたコードを参照してください....これは非常に非常にnciely-問題なく実行されます:それは素敵なフォーマットのcvs-outputを吐き出します!!

#!/usr/bin/perl
use warnings;
use strict;
use LWP::Simple;
use HTML::TableExtract;
use Text::CSV;

my $html= get 'http://192.68.214.70/km/asps/schulsuche.asp?q=n&a=50';
$html =~ tr/r//d;     # strip the carriage returns
$html =~ s/&nbsp;/ /g; # expand the spaces

my $te = new HTML::TableExtract();
$te->parse($html);

my @cols = qw(
    rownum
    number
    name
    phone
    type
    website
);

my @fields = qw(
    rownum
    number
    name
    street
    postal
    town
    phone
    fax
    type
    website
);

my $csv = Text::CSV->new({ binary => 1 });

foreach my $ts ($te->table_states) {
    foreach my $row ($ts->rows) {

trim leading/trailing whitespace from base fields
        s/^s+//, s/\s+$// for @$row;

load the fields into the hash using a "hash slice"
        my %h;
        @h{@cols} = @$row;

derive some fields from base fields, again using a hash slice
        @h{qw/name street postal town/} = split /n+/, $h{name};
        @h{qw/phone fax/} = split /n+/, $h{phone};

trim leading/trailing whitespace from derived fields
        s/^s+//, s/\s+$// for @h{qw/name street postal town/};

        $csv->combine(@h{@fields});
        print $csv->string, "\n";
    }
} 

注:この上記のコードはうまく動作します-csv形式の出力を吐き出します。

4

2 に答える 2

1

素晴らしい!複数のページを自分で取得する方法を理解していただくのを待っていました。

1)コードをページ取得ループに配置します(「}」を最後まで移動します)。

2)$ html =$pageurlを取得します; #これを変更して新しいURLを使用する

3)バックスラッシュを元の場所に戻します:tr / \ r // d;

于 2011-02-26T00:04:29.777 に答える
1

ページングを実現するための別のアプローチは、ページからすべてのURLを抽出し、ポケットベルのURLを検出することです。

... 
for (@urls) { 
    if (is_pager_url($_) and not exists $seen{$_}) {
         push @pager_url, $_; 
         $seen{$_}++; 
    }
}
... 

sub is_pager_url { 
    my ($url) = @_; 
    return 1 if $url =~ m{schulsuche.asp\?q=e\&a=\d+\&s=\d+};
}

このようにして、カウンターの増分や総ページ数の設定を行う必要はありません。また、aとsのさまざまな値に対しても機能します。%seenハッシュを保持することにより、前のページと次のページを区別することを安価に回避できます。

于 2011-02-26T00:13:18.860 に答える