Perl中的模式所需的单行正则表达式

时间:2011-03-25 14:26:40

标签: html regex perl match

我需要使用perl读取包含类似结构的许多HTML文件。

结构由 STRRRR ... E

  • S =表格开始前的html标题
  • T = html文件中的唯一表格启动结构(我可以识别它)
  • R =一组html元素(那些是tr,我也可以识别它)
  • E =所有剩余的 - 结束R的结束

我想使用单行“m”perlop提取数组中的所有R。

我正在寻找类似的东西:

  

@all_Rs = $ htmlfile = ~m {ST(R)* E} gs;

但它从来没有成功过。

到目前为止,我一直在努力解决这个问题,比如使用删除不需要的文本,for循环等。 我想从此页面中提取所有行:http://www.trainenquiry.com/StaticContent/Railway_Amnities/Enquiry%20-%20North/STATIONS.aspx 并且有很多这样的页面。

3 个答案:

答案 0 :(得分:5)

正则表达式是错误的工具。使用HTML解析器。

use HTML::TreeBuilder::XPath;
my $tree= HTML::TreeBuilder::XPath->new_from_content(<<'END_OF_HTML');
<html>
    <table>
        <tr>1
        <tr>2
        <tr>3
        <tr>4
        <tr>5
    </table>
</html>
END_OF_HTML

print $_->as_text for $tree->findnodes('//tr');

HTML::TreeBuilder::XPath继承自HTML::TreeBuilder

答案 1 :(得分:2)

daxim是关于使用真正的解析器的。我个人的选择是XML::LibXML

use XML::LibXML
my $parser = XML::LibXML->new();
$parser->recover(1);                 # don't fail on parsing errors
my $doc = do { 
    local $SIG{__WARN__} = sub {};   # silence warning about parsing errors
    $parser->parse_html_file('http://www.trainenquiry.com/StaticContent/Railway_Amnities/Enquiry%20-%20North/STATIONS.aspx');
};

print $_->toString() for $doc->findnodes('//tr[td[1][@class="td_background"]]');

这可以从该页面获取每个站点行。

对于更多的工作,我们可以有一个很好的数据结构来保存每个单元格中的文本。

use Data::Dumper;
my @data = map {
    my $row = $_;
    [ map {
        $_->findvalue('normalize-space(text())');
    } $row->findnodes('td') ]
} $doc->findnodes('//tr[td[1][@class="td_background"]]');
print Dumper \@data;

答案 2 :(得分:2)

如果要处理HTML表,请考虑使用知道如何处理HTML表的模块!

#!/usr/bin/perl
use warnings;
use strict;
use LWP::Simple;
use HTML::TableExtract;


my $html = get 'http://www.trainenquiry.com/StaticContent/Railway_Amnities/Enquiry%20-%20North/STATIONS.aspx';
$html =~ s/&nbsp;/ /g;

my $te = new HTML::TableExtract( depth => 1, count => 2 );
$te->parse($html);
foreach my $ts ($te->table_states) {
   foreach my $row ($ts->rows) {
      next if $row->[0] =~ /^\s*(Next|Station)/;
      next if $row->[4] =~ /^\s*(ARR\/DEP|RESERVATION)/;
      foreach my $cell (@$row) {
          $cell =~ s/^\s+//;
          $cell =~ s/\s+$//;
          print "$cell\n";
      }
      print "\n";
   }
}