Небольшая помощь в разборе Perl HTML - PullRequest
1 голос
/ 02 июля 2010

Я работаю над небольшой программой на Perl, которая откроет сайт, найдет слова «Отчеты о граде» и вернет мне информацию. Я очень плохо знаком с Perl, поэтому некоторые из них могут быть легко исправлены. Сначала мой код говорит, что я использую унифицированное значение. Вот что у меня есть

#!/usr/bin/perl -w
use LWP::Simple;

my $html = get("http://www.spc.noaa.gov/climo/reports/last3hours.html")
    or die "Could not fetch NWS page.";
$html =~ m{Hail Reports} || die;
my $hail = $1;
print "$hail\n";

Во-вторых, я думал, что регулярные выражения - это самый простой способ делать то, что я хочу, но я не уверен, что смогу сделать это с ними. Я хочу, чтобы моя программа искала слова «Отчеты о граде» и отправляла мне информацию между «Отчетами о граде» и словами «Отчеты о ветре». Это возможно с регулярными выражениями или я должен использовать другой метод? Вот фрагмент исходного кода веб-страниц, который я хочу отправить обратно

     <tr><th colspan="8">Hail Reports (<a href="last3hours_hail.csv">CSV</a>)&nbsp;(<a href="last3hours_raw_hail.csv">Raw Hail CSV</a>)(<a href="/faq/#6.10">?</a>)</th></tr> 

#The Data here will change throughout the day so normally there will be more info.
      <tr><td colspan="8" class="highlight" align="center">No reports received</td></tr> 
      <tr><th colspan="8">Wind Reports (<a href="last3hours_wind.csv">CSV</a>)&nbsp;(<a href="last3hours_raw_wind.csv">Raw Wind CSV</a>)(<a href="/faq/#6.10">?</a>)</th></tr> 

Ответы [ 4 ]

3 голосов
/ 03 июля 2010

Использует одиночные и многострочные совпадения.Кроме того, он выбирает только первое совпадение для промежуточного текста, что будет немного быстрее, чем жадность.

#!/usr/bin/perl -w

use strict;
use LWP::Simple;

   sub main{
      my $html = get("http://www.spc.noaa.gov/climo/reports/last3hours.html")
                 or die "Could not fetch NWS page.";

      # match single and multiple lines + not greedy
      my ($hail, $between, $wind) = $html =~ m/(Hail Reports)(.*?)(Wind Reports)/sm
                 or die "No Hail/Wind Reports";

      print qq{
               Hail:         $hail
               Wind:         $wind
               Between Text: $between
            };
   }

   main();
3 голосов
/ 03 июля 2010

Предупреждение о неинициализированном значении исходит от $ 1 - оно нигде не определено и не установлено.

Для уровня строки вместо байтового уровня «между» вы можете использовать:

for (split(/\n/, $html)) {
    print if (/Hail Reports/ .. /Wind Reports/ and !/(?:Hail|Wind) Reports/);
}
2 голосов
/ 02 июля 2010

Вы ничего не захватывали за 1 доллар, потому что ни одно из ваших регулярных выражений не было заключено в скобки. Следующее работает для меня.

#!/usr/bin/perl
use strict;
use warnings;

use LWP::Simple;

my $html = get("http://www.spc.noaa.gov/climo/reports/last3hours.html")
    or die "Could not fetch NWS page.";

$html =~ m{Hail Reports(.*)Wind Reports}s || die; #Parentheses indicate capture group
my $hail = $1; # $1 contains whatever matched in the (.*) part of above regex
print "$hail\n";
1 голос
/ 02 июля 2010

Строки захвата скобок в регулярных выражениях. У вас нет круглых скобок в регулярном выражении, поэтому $ 1 не установлен ни к чему. Если у вас было:

$html =~ m{(Hail Reports)} || die;

Тогда $ 1 будет установлен в «Отчеты о приветствии», если он существует в переменной $ html. Поскольку вам нужно только знать, соответствует ли оно, то вам действительно не нужно ничего захватывать на этом этапе, и вы можете написать что-то вроде:

unless ( $html =~ /Hail Reports/ ) {
  die "No Hail Reports in HTML";
}

Чтобы захватить что-то между строками, вы можете сделать что-то вроде:

if ( $html =~ /(?<=Hail Reports)(.*?)(?=Wind Reports)/s ) {
  print "Got $1\n";
}
...