0

我目前正在研究一个小解析器。

我的第一个脚本取得了非常好的结果!这能够运行得很好!它从页面中获取数据:http: //192.68.214.70/km/asps/schulsuche.asp ?q=n&a=20(注意 6142 条记录) - 但请注意 - 数据没有分开,因此随后使用数据有点难。因此我有第二个脚本 - 见下文!

注意 - 朋友们帮助我完成了这两个脚本。我需要介绍自己是一个真正的新手,需要二合一的迁移帮助。所以,你看,我的 Perl 知识并没有那么详细,以至于我能够自己迁移到一个!任何和所有的帮助都会很棒!

第一个脚本:蜘蛛和解析器:它会像这样吐出数据:

lfd. Nr. Schul- nummer Schulname Straße PLZ Ort Telefon Fax Schulart Webseite
1 0401 Mädchenrealschule Marienburg, Abenberg, der Diözese Eichstätt Marienburg 1 91183  Abenberg   09178/509210  Realschulen  mrs-marienburg.homepage.t-online.de 
2 6581 Volksschule Abenberg (Grundschule) Güssübelstr. 2 91183  Abenberg   09178/215 09178/905060 Volksschulen  home.t-online.de/home/vs-abenberg 
3 6913 Mittelschule Abenberg  Güssübelstr. 2 91183  Abenberg   09178/215 09178/905060 Volksschulen  home.t-online.de/home/vs-abenberg 
4 0402 Johann-Turmair-Realschule Staatliche Realschule Abensberg Stadionstraße 46 93326  Abensberg   09443/9143-0,12,13 09443/914330 Realschulen  www.rs-abensberg.de 

但我需要分隔数据:用逗号或类似的东西!

我有第二个脚本。这部分可以做 CSV 格式。我想将它与蜘蛛逻辑结合起来。但首先让我们看一下第一个脚本:具有出色的蜘蛛逻辑。

请参阅适当的代码:

 #!/usr/bin/perl
    use strict;
    use warnings;
    use HTML::TableExtract;
    use LWP::Simple;
    use Cwd;
    use POSIX qw(strftime);
    my $te = HTML::TableExtract->new;
    my $total_records = 0;
    my $suchbegriffe = "e";
    my $treffer = 50;
    my $range = 0;
    my $url_to_process = "http://192.68.214.70/km/asps/schulsuche.asp?q=";
    my $processdir = "processing";
    my $counter = 50;
    my $displaydate = "";
    my $percent = 0;

    &workDir();
    chdir $processdir;
    &processURL();
    print "\nPress <enter> to continue\n";
    <>;
    $displaydate = strftime('%Y%m%d%H%M%S', localtime);
    open OUTFILE, ">webdata_for_$suchbegriffe\_$displaydate.txt";
    &processData();
    close OUTFILE;
    print "Finished processing $total_records records...\n";
    print "Processed data saved to $ENV{HOME}/$processdir/webdata_for_$suchbegriffe\_$displaydate.txt\n";
    unlink 'processing.html';
    die "\n";

    sub processURL() {
    print "\nProcessing $url_to_process$suchbegriffe&a=$treffer&s=$range\n";
    getstore("$url_to_process$suchbegriffe&a=$treffer&s=$range", 'tempfile.html') or die 'Unable to get page';

       while( <tempfile.html> ) {
          open( FH, "$_" ) or die;
          while( <FH> ) {
             if( $_ =~ /^.*?(Treffer <b>)(d+)( - )(d+)(</b> w+ w+ <b>)(d+).*/ ) {
                $total_records = $6;
                print "Total records to process is $total_records\n";
                }
             }
             close FH;
       }
       unlink 'tempfile.html';
    }

    sub processData() {
       while ( $range <= $total_records) {
          getstore("$url_to_process$suchbegriffe&a=$treffer&s=$range", 'processing.html') or die 'Unable to get page';
          $te->parse_file('processing.html');
          my ($table) = $te->tables;
          for my $row ( $table->rows ) {
             cleanup(@$row);
             print OUTFILE "@$row\n";
          }
          $| = 1; 
          print "Processed records $range to $counter";
          print "\r";
          $counter = $counter + 50;
          $range = $range + 50;
          $te = HTML::TableExtract->new;
       }
    }

    sub cleanup() {
       for ( @_ ) {
          s/s+/ /g;
       }
    }

    sub workDir() {
    # Use home directory to process data
    chdir or die "$!";
    if ( ! -d $processdir ) {
       mkdir ("$ENV{HOME}/$processdir", 0755) or die "Cannot make directory $processdir: $!";
       }
    }  

但是由于上面的脚本-不幸的是,我没有照顾分隔符,所以我不得不照顾一种方法,它确实会寻找分隔符。为了得到数据(输出)分离。

因此,通过分离,我能够处理数据 - 并将其存储在 mysql 表中.. 或做其他事情......所以这里 [下面] 是位 - 计算出 csv-formate 注意 - 我想要将下面的代码放入上面的代码中 - 将上述代码的蜘蛛逻辑与以 CSV 格式输出数据的逻辑相结合。在代码中设置的位置问题:我们能否确定这一点以将一个迁移到另一个...!?那太棒了……我希望我能弄清楚我的想法……!?我们是否能够利用这两个部分(/scripts)的好处将它们迁移到一个中?

所以问题是:在脚本中设置 CSV 脚本的位置(上图)

#!/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=a&a=20';
$html =~ tr/\r//d;     # strip carriage returns
$html =~ s/&nbsp;/ /g; # expand 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";
    }
}

问题是我在第一个脚本中取得了非常好的结果!它从页面中获取数据:http: //192.68.214.70/km/asps/schulsuche.asp ?q=n&a=20 (注意 6142 条记录) - 但请注意 - 数据没有分开......!

我有第二个脚本。这部分可以做 CSV 格式。我想将它与蜘蛛逻辑结合起来。

要插入的零件在哪里?我期待着任何和所有的帮助。

如果我必须更准确 - 请告诉我...

4

1 回答 1

3

既然你已经输入了一个完整的脚本,我假设你想要对整个事情进行批评。

#!/usr/bin/perl
    use strict;
    use warnings;
    use HTML::TableExtract;
    use LWP::Simple;
    use Cwd;
    use POSIX qw(strftime);
    my $te = HTML::TableExtract->new;

既然你只$te在一个块中使用,你为什么要在这个外部范围内声明和初始化它?同样的问题适用于您的大多数变量——尽量在最内层范围内声明它们。

    my $total_records = 0;
    my $suchbegriffe = "e";
    my $treffer = 50;

一般来说,英文变量名将使您能够与比德文名称更多的人合作。我懂德语,所以我了解您的代码的意图,但大多数 SO 都没有。

    my $range = 0;
    my $url_to_process = "http://192.68.214.70/km/asps/schulsuche.asp?q=";
    my $processdir = "processing";
    my $counter = 50;
    my $displaydate = "";
    my $percent = 0;

    &workDir();

不要&用来调用潜艇。只需调用他们workDir;。自 1994 年以来就没有必要使用&它,它可能会导致一个令人讨厌的问题,因为&callMySub;它是一种特殊情况,它不会做你可能认为的事情,而callMySub;会做正确的事情。

    chdir $processdir;
    &processURL();
    print "\nPress <enter> to continue\n";
    <>;
    $displaydate = strftime('%Y%m%d%H%M%S', localtime);
    open OUTFILE, ">webdata_for_$suchbegriffe\_$displaydate.txt";

这些天通常首选词法文件句柄:open my $outfile, ">file";此外,您应该检查打开的错误或use autodie;在失败时使打开死亡。

    &processData();
    close OUTFILE;
    print "Finished processing $total_records records...\n";
    print "Processed data saved to $ENV{HOME}/$processdir/webdata_for_$suchbegriffe\_$displaydate.txt\n";
    unlink 'processing.html';
    die "\n";

    sub processURL() {
    print "\nProcessing $url_to_process$suchbegriffe&a=$treffer&s=$range\n";
    getstore("$url_to_process$suchbegriffe&a=$treffer&s=$range", 'tempfile.html') or die 'Unable to get page';

       while( <tempfile.html> ) {
          open( FH, "$_" ) or die;
          while( <FH> ) {
             if( $_ =~ /^.*?(Treffer <b>)(d+)( - )(d+)(</b> w+ w+ <b>)(d+).*/ ) {
                $total_records = $6;
                print "Total records to process is $total_records\n";
                }
             }
             close FH;
       }
       unlink 'tempfile.html';
    }

    sub processData() {
       while ( $range <= $total_records) {
          getstore("$url_to_process$suchbegriffe&a=$treffer&s=$range", 'processing.html') or die 'Unable to get page';
          $te->parse_file('processing.html');
          my ($table) = $te->tables;
          for my $row ( $table->rows ) {
             cleanup(@$row);
             print OUTFILE "@$row\n";

如果您想用逗号分隔数据,则需要更改此行。看看join函数,它可以为所欲为。

          }
          $| = 1; 
          print "Processed records $range to $counter";
          print "\r";
          $counter = $counter + 50;
          $range = $range + 50;
          $te = HTML::TableExtract->new;
       }

在循环结束而不是开始进行初始化是很奇怪的。在循环顶部$te声明和初始化更为惯用。$te

    }

    sub cleanup() {
       for ( @_ ) {
          s/s+/ /g;

你的意思是s/\s+/ /g;

       }
    }

    sub workDir() {
    # Use home directory to process data
    chdir or die "$!";
    if ( ! -d $processdir ) {
       mkdir ("$ENV{HOME}/$processdir", 0755) or die "Cannot make directory $processdir: $!";
       }
    }  

我没有评论你的第二个剧本;也许您应该将其作为一个单独的问题提出。

于 2011-02-20T12:21:56.870 回答