2016-07-07 35 views
1

我試圖從EnviroCanada天氣頁面中提取以下內容。如何解析網頁

我想按照以下每個小時獲得。

時間|大腿| Tlow |溼度

7:00 | 23 | 22.9 | 30

提取HTML頁:

<tr> 
     <td headers="header1" class="text-center vertical-center"> 7:00 </td> 
     <td headers="header2" class="media vertical-center"><span class="pull-left"><img class="media-object" height="35" width="35" src="/weathericons/small/02.png" /></span><div class="visible-xs visible-sm"> 
      <br /> 
      <br /> 
      </div> 
      <div class="media-body"> 
      <p>Partly Cloudy</p> 
      </div> 
     </td> 
     <td headers="header3m" class=" metricData text-center vertical-center">23 
              �(22.9) 
             </td> 
     <td headers="header3i" class=" imperialData hidden text-center vertical-center">73 
              �(73.2) 
             </td> 
     <td headers="header4m" class="metricData text-center vertical-center"> 
      <abbr title="West-Northwest">WNW</abbr> 8</td> 
     <td headers="header4i" class="imperialData hidden text-center vertical-center"> 
      <abbr title="West-Northwest">WNW</abbr> 5</td> 
     <td headers="header6" class="metricData text-center vertical-center">30</td> 
     <td headers="header6" class="imperialData hidden text-center vertical-center">87</td> 
     <td headers="header7" class="text-center vertical-center">83</td> 
     <td headers="header8" class="metricData text-center vertical-center">20</td> 
     <td headers="header8" class="imperialData hidden text-center vertical-center">68</td> 
     <td headers="header9m" class="metricData text-center vertical-center">100.7</td> 
     <td headers="header9i" class="imperialData hidden text-center vertical-center">29.7</td> 
     <td headers="header10" class="metricData text-center vertical-center">24</td> 
     <td headers="header10" class="imperialData hidden text-center vertical-center">15</td> 
     </tr> 

到目前爲止的代碼:

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


my $url = "http://weather.gc.ca/past_conditions/index_e.html?station=yyz"; 
my $page = get($url) || 
die "Could not load URL\n"; 


my $parser = HTML::TokeParser->new(\$page) || 
die "Parse error\n"; 

$parser->get_tag("td") foreach(); 
$parser->get_tag(""); 
my $time = $parser->get_text(); 

    ?? 
my $thigh = $parser->get_text(); 


??? 
my $tlow = $parser->get_text(); 

??? 
my $humid = $parser->get_text(); 

我完全失去了這裏

+1

[HTML :: TableExtract非常有用](https://www.nu42。COM/2012/04/htmltableextract-IS-beautiful.html)。 –

+0

我喜歡Mojo :: DOM從HTML頁面獲取東西,非常好用。 – asjo

回答

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 
... 

評論。

屬性爲new使其僅在這些標題下提取列。循環變量是一個參考,與行元素的數組。元素是單元格中的原始文本。

第一行跳過沒有預期格式的行–可能的數字\d?後跟另一個數字,然後:然後是兩個數字。這是時間,3:0003:00

爲清楚起見,arrayref $rrow被提取到數組@row中。 特定列中的搜索元素,@row[0,2]正在使用。 $row[1]中的一個被正則表達式解析,該正則表達式捕獲一個數字(\d+),然後用.分隔兩個數字,並可能插入文本(.*)。這些捕獲由regex返回,並分配給其他兩個變量。

有關參考文獻perlreftut和正則表達式perlretut的信息,請參閱模塊的文檔以及必要的參考資料。另一個有用的頁面是數據結構菜譜perldsc。其他介紹見Tutorials。他們通常會鏈接到更具體的文檔。

+0

問題是我如何提取3:00,5:00等並放置在適當的列?它們都屬於相同的標題標籤。 – BrianB

+0

我試過HTML :: TableExtract(簡單測試),它不喜歡'我的foreach':使用LWP :: Simple; 使用HTML :: TableExtract; 使用Text :: Table; my $ doc ='http://weather.gc.ca/past_conditions/index_e.html?station=yyz'; my $ headers = ['Time','Temperature']; my $ table_extract = HTML :: TableExtract-> new(headers => $ headers); my $ table_output = Text :: Table-> new(@ $ headers); $ table_extract-> parse_file($ doc); my($ table)= $ table_extract-> tables; ($ table-> rows){ clean_up_spaces($ row); #爲簡潔起見未顯示 $ table_output-> load($ row); } print $ table_output; – BrianB

+0

@BrianB我已經發布了一些基本的但工作的代碼。當我得到時間時會清理它(儘管看起來你不需要它!)。讓我知道事情的後續。 – zdim