如何使用Perl正则表达式从HTML文件中提取信息?

时间:2011-10-16 11:02:27

标签: html xml regex perl

我有两个文件,XML和HTML,需要从某些模式中提取数据。

我的XML文件格式很好,我可以使用readline读取一行并在标签之间搜索数据。

if($line =~ /\<tag1\>$varvalue\<\/tag1\>/)`

然而,对于我的HTML,它有我见过的最糟糕的代码之一,文件是:

<div class="theater">
    <h2>
    <a href="/showtimes/university-village-3" >**University Village 3**</a></h2>
    <div class="address">
        <i>**3323 South Hoover Street, Los Angeles CA 90007 | (213) 748-6321**</i>
    </div>
</div>

<div class="mtitle">
    <a href="/movie/dream-house-2011"  title="Dream House" onmouseover="mB(event, 771204354);"  >**Dream House**</a>
    <span>**(PG-13 , 1 hr. 31 min.)**</span>
</div>

<div class="times">

    **1:00 PM,**
</div>

现在从这个文件我需要选择以粗体显示的数据。

我可以使用Perl正则表达式来搜索此文件中的数据。

2 个答案:

答案 0 :(得分:6)

RegEx match open tags except XHTML self-contained tags

http://www.codinghorror.com/blog/2009/11/parsing-html-the-cthulhu-way.html

Using regular expressions to parse HTML: why not?

当你读完那些回来后:)

编辑:要实际解决您的问题,请看一下这个模块:

http://perlmeme.org/tutorials/html_parser.html

解析html文件的一些示例:

#!/usr/local/bin/perl

use HTML::TreeBuilder;

$tree = HTML::TreeBuilder->new;
$tree->parse_file('C:\Users\Stefanos\workspace\HTML_Parser_Test\test.html');

@divs = $tree->find('div');

$tree->delete;

在这个例子中,我只使用你的标签作为.html文件的主体。 div存储在@divs数组中。因为我不知道你想找哪个文本,因为**不是一个元素,我无法帮你进一步..

P.S。我从来没有使用过这个模块,但我只是在5分钟内完成了它,因此解析html文件并找到你想要的东西并不是那么难......

正则表达式匹配任何特定标记和内容存储结果为$ 1:

if ($subject =~ m!<tagname[^>]*>(.*?)</tagname>!s) {
    # Successful match
}

虽然在嵌套元素时很快就会意识到这种方法的局限性。

将tagname替换为实际标记..例如在你的情况下我,a,span,div虽然对于div你也会得到第一个div的内容,这不是你想要的..

答案 1 :(得分:0)

Parsing XML and HTML using regular expressions is a fool's errand。有许多简单易用的Perl模块用于解析HTML。这是使用HTML::TokeParser::Simple的内容。我省略了将电影和放映时间与影院相关联的代码(因为我无意构建合适的输入文件):

#!/usr/bin/env perl

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

my $parser = HTML::TokeParser::Simple->new(handle => \*DATA);

my @theaters;

while (my $div = $parser->get_tag('div')) {
    my $class = $div->get_attr('class');
    next unless defined($class) and $class eq 'theater';

    my %record;

    $record{theater} = $parser->get_text('/a');
    $record{address} = $parser->get_text('/i');

    s{(?:^\s+)|(?:\s+\z)}{} for values %record;

    push @theaters, \%record;
}

use YAML;
print Dump \@theaters;

__DATA__
<div class="theater">
    <h2>
    <a href="/showtimes/university-village-3" >**University Village 3**</a></h2>
    <div class="address">
        <i>**3323 South Hoover Street, Los Angeles CA 90007 | (213) 748-6321**</i>
    </div>
</div>

<div class="mtitle">
    <a href="/movie/dream-house-2011"  title="Dream House" onmouseover="mB(event, 771204354);"  >**Dream House**</a>
    <span>**(PG-13 , 1 hr. 31 min.)**</span>
</div>

<div class="times">

    **1:00 PM,**
</div>

<div class="theater">
    <h2>
    <a href="/showtimes/university-village-3" >**Some other theater*</a></h2>
    <div class="address">
        <i>**1234 South Hoover Street, St Paul, MN 99999 | (999) 748-6321**</i>
    </div>
</div>

输出:

[sinan@macardy]:~/tmp> ./tt.pl
---
- address: '**3323 South Hoover Street, Los Angeles CA 90007 | (213) 748-6321**'
  theater: '**University Village 3**'
- address: '**1234 South Hoover Street, St Paul, MN 99999 | (999) 748-6321**'
  theater: '**Some other theater*'