如何解析网页

时间:2016-07-07 17:57:07

标签: perl lwp

我试图从EnviroCanada天气页面中提取以下内容。

我试图按照以下方式获得每小时。

时间|大腿| Tlow |湿度

7:00 | 23 | 22.9 | 30

提取的HTML页面:

require(['module name'])
到目前为止

代码:

require

我完全迷失在这里

1 个答案:

答案 0 :(得分:4)

使用LWP::Simple获取页面后,您可以根据需要使用它来选择特定工具,而不是使用常规解析器。

在这种情况下,您手上有一张桌子,我建议HTML::TableExtract。有了它,您可以通过多种方式干净地检索表格元素,然后处理它们。它可以使用多个表,使用标题,设置解析首选项等。通常,您甚至不必查看实际的HTML。该模块是HTML::Parser的子类。根据我的经验,它是一个非常好的工具。

以下是针对此特定页面和任务的一些基本代码。

use warnings;
use strict;
use LWP::Simple;
use HTML::TableExtract;

my $url = "http://weather.gc.ca/past_conditions/index_e.html?station=yyz";
my $page = get($url) or die "Can't load $url: $!";

my $headers = [ 'Time', 'Temperature', 'Humidex' ];

my $tec = HTML::TableExtract->new(headers => $headers);
$tec->parse($page);

my $fmt = "%6s | %6s | %6s | %8s\n";    
printf($fmt, 'Time', 'T-high', 'T-low', 'Humidex');    

my ($time, $temp_hi, $temp_low, $hum);

foreach my $rrow ($tec->rows) {
    # Skip rows without expected data. Clean up leading/trailing spaces.
    next if $rrow->[0] !~ /^\s*\d?\d:\d\d/;
    my @row = map { s|^\s*||; s|\s*$||; $_ } @$rrow;
    # Process as needed
    ($time, $hum) = @row[0,2];
    ($temp_hi, $temp_low) = $row[1] =~ /(\d+) .* \( (\d+\.\d+) \)/xs;
    printf($fmt, $time, $temp_hi, $temp_low, $hum);
}

输出的前几行

  Time | T-high |  T-low |  Humidex
 16:00 |     29 |   29.2 |       37
 15:00 |     27 |   27.2 |       37
 14:00 |     26 |   25.6 |       33
...

评论

headers的{​​{1}}属性使其仅在这些标题下提取列。循环变量是引用,是带有行元素的数组。元素是单元格中的原始文本。

第一行会跳过不具有预期格式的行 - 可能的数字new后跟另一个数字,然后是\d?,然后是两位数。这是时间:3:00

为清晰起见,arrayref 03:00被提取到数组$rrow中。 特定列中的搜索元素@row在它们到来时使用。 @row[0,2]中的一个由正则表达式解析,该正则表达式捕获一个数字$row[1],然后是两个以(\d+)分隔的数字,并带有可能的插入文本(.)。这些捕获由正则表达式返回,并分配给其他两个变量。

请参阅模块的文档,如果需要,请参阅参考perlreftut和正则表达式perlretut的教程。另一个有用的页面是Data Structures Cookbook perldsc。有关其他介绍,请参阅Tutorials。它们通常包含指向更具体文档的链接。