【问题标题】:How can I extract these table rows from HTML? [closed]如何从 HTML 中提取这些表格行? [关闭]
【发布时间】:2021-04-06 09:06:35
【问题描述】:

我想通过匹配后输入团队来查找团队分数,然后在团队名称后显示下一个数字或单词以便能够显示分数。

我希望这适用于左右球队(左侧:水晶宫 1 - 右侧:1 莱斯特)

主要问题是从我们匹配的进入团队中找到团队得分。

#!/usr/bin/perl -wT

use strict;
use warnings;
use CGI;
use HTML::TableExtract;
use LWP::UserAgent;

my $cgi = CGI->new;
my $ua = LWP::UserAgent->new;


my $input = $cgi->param("team");
my $response ='';


if ($input) {
my $req = HTTP::Request->new(GET => "");
my $res = $ua->request($req);
my $html = $res->decoded_content;

$html =~ s/<span.*?<\/span>//gs;
$html =~ s/<script.*?<\/script>//gs;
$html =~ s/<td(?=[^>]*class="events-button button first-occur")[^>]*>//gs;

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

print "Content-type: text/html\n\n";

foreach my $row ($table->rows) {
     my $output =  join("", @$row);
     $output =~ s/\R//g;
     print $output;
     
    # Find matching team (Its a must to find team after word FT)
    if ($output =~ m/$input/) {
    
    # After that team the next is score (Gets team scores)
    my $score = $output =~ /$input\s*?(\S+)/;
    
    $response ="Found Team And Score is: $score";
    } else {
    $response ="Can't find team";
  }
}
}


print <<EOF;

<!DOCTYPE html>
<html>
<body>

<h1>Test</h1>

<form method="post">
  <label for="team">Enter Team:</label>
  <input type="text" name="team"><br><br>
  <input type="submit" value="Find team">
</form>

 <h4>$response</h4>

</body>
</html>
EOF

【问题讨论】:

    标签: perl parsing


    【解决方案1】:

    我喜欢将 Mojolicious 用于这些事情,因为我需要的一切都是内置的。借助一点 CSS 选择器魔法,您可以轻松地将所需数据归零,而无需手动处理字符串。

    查看源代码,我看到该页面的结果是类matches_new 的表,并且在该表中,有趣的行具有类match。在这些行中,有趣的表格单元格位于 team-ateam-bscore-time 类中(尽管“分数”也可能是游戏状态)。

    请注意,在您单击团队名称之前,许多行不会加载其数据。那是 JavaScript 在起作用,而 Perl 网络抓取库不会在这方面为您提供帮助。我不知道为什么英超联赛已经为我填写了数据(每个人都这样吗?)或者我们是否可以依赖这种情况。

    但是让我们提取这些数据。

    Mojo HTML 解析的基本过程是发出请求,然后获取 DOM(文档对象模型)。在该 DOM 中,findat 定位特定部分。 find 获取与其 CSS 选择器匹配的所有内容,at 获取下一个匹配项。

    所以,我 find 所有正确的行,每一行都是另一个(较小的)DOM 对象,我可以进一步探索以获得团队和得分。

    find 返回一个 Mojo::Collection(数组的花哨接口),我调用 map 依次处理每一行并从每个表格单元格中提取所有文本(trim 删除前导和尾随空格)。 all_text 获取所有内容,包括子节点中的文本。

    #!perl
    use v5.10;
    
    use Mojo::UserAgent;
    use Mojo::Util qw(dumper trim);
    
    my $url = 'https://int.soccerway.com/matches/2020/12/28/';
    
    my $ua = Mojo::UserAgent->new;
    
    my @results = $ua
        ->get( $url )
        ->result
        ->dom
        ->find( 'table.matches_new tr.match' )
        ->map( sub {
            my $row = $_;
            my @results =
                map { trim( $row->at( $_ )->all_text ) }
                qw( td.team-a td.team-b td.score-time );
            return \@results;
            } )
        ->to_array;
    
    say dumper( @results );
    

    这是输出,只有足球比赛:

    [
      [
        "Everton",
        "Manchester City",
        "PSTP"
      ],
      [
        "Crystal Palace",
        "Leicester City",
        "1 - 1"
      ],
      [
        "Chelsea",
        "Aston Villa",
        "1 - 1"
      ]
    ]
    

    使用 LWP 或 HTTP::Request 并没有完全“错误”,但它们没有提供强大的工具来处理数据。 HTML::TableExtract 很好,但是它得到的那个表很长,你不想要它的大部分行。在我的职业生涯中,我编写了很多很多程序,就像您介绍的那样:获取源代码,尽可能删除不相关的 HTML,并处理剩下的内容。将所有工具放在一个包中,让所有东西都可以在同一个环境中协同工作,这样会更好。

    使用选择器准确定位您想要的目标更容易、更不脆弱且代码更少。你可以在Mojo docs 中看到这一点,我在Mojo Web Clients 中详细地写了很多例子。

    此外,只要您有 HTML,您就可以使用 Mojo::DOM 的东西,无论来源如何。我在 Extracting from HTML with Mojo::DOM 为 Perl.com 写了这篇文章。对你来说,把你解码的内容交给 Mojo::DOM 并做我已经做过的同样的处理:

    my $html = HTTP::Request->new( ... )->request( ... )->decoded_content;
    
    my $dom = Mojo::DOM->new( $html );
    my @results = $dom->find( ... )->...;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-03-02
      • 2018-07-07
      • 1970-01-01
      • 2020-10-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-23
      相关资源
      最近更新 更多