5

自从我问如何使用正则表达式解析 html 并受到了一些打击(理所当然),我一直在研究HTML::TreeBuilderHTML::ParserHTML::TokeParserHTML::Elements Perl 模块。

我有这样的 HTML:

<div id="listSubtitlesFilm">
  <dt id="a1">
    <a href="/45/subtitles-67624.aspx">
      .45 (2006)
    </a>
  </dt>
</div>

我想解析出/45/subtitles-67624.asp,但更重要的是我想知道如何解析出 div 的内容

我在上一个问题上得到了这个例子:

while ( my $anchor = $parser->get_tag('a') ) {
    if ( my $href = $anchor->get_attr('href') ) {
 #http://subscene.com/english/Sit-Down-Shut-Up-First-Season/subtitles-272112.aspx
        push @dnldLinks, $1 if $href =~ m!/subtitle-(\d{2,8})\.aspx!;
    }

这非常有效,但是当我尝试对其进行一些编辑并在“div”上使用它时,它不起作用。这是我尝试过的代码:

我尝试使用此代码:

while (my $anchor = $p->get_tag("dt")) {
  if($stuff = $anchor->get_attr('a1')) {
    print $stuff."\n";
  }
}
4

5 回答 5

5

您可以使用(又一个模块!)HTML::TreeBuilder::XPath,根据它的名称,它可以让您在 HTML::TreeBuilder 对象上使用 XPath。

#!/usr/bin/perl

use strict;
use warnings;

use HTML::TreeBuilder::XPath;

my $root = HTML::TreeBuilder::XPath->new_from_file( "my.html");

# print $root->as_HTML; # useful to see how HTML::TreeBuilder
# understands your HTML. For example it will wrap the implied
# dl element around dt, which you need to take into account
# when writing the XPath query below

my $id= "a1";
# you need the .//dt because of the extra dl
my @divs= $root->findnodes( qq{//div[.//dt[\@id="$id"]]});

print $divs[0]->as_HTML; # or as_text
于 2009-11-07T08:35:30.927 回答
5

为了解决您的具体问题,给定 HTML:

<div id="listSubtitlesFilm">
  <dt id="a1">
    <a href="/45/subtitles-67624.aspx">
      .45 (2006)
    </a>
  </dt>
</div>

我假设您对锚文本感兴趣,即".45 (2006)"在这种情况下,但前提是锚出现在div带有 id的 a 中listSubtitlesFilm

#!/usr/bin/perl

use strict;
use warnings;

use HTML::TokeParser::Simple;

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

my @dnldLinks;

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

    my $anchor = $parser->get_tag('a');
    my $href = $anchor->get_attr('href');
    next unless defined($href)
        and $href =~ m!/subtitles-(\d{2,8})\.aspx\z!;
    push @dnldLinks, [$parser->get_trimmed_text('/a'), $1];
}

use Data::Dumper;
print Dumper \@dnldLinks;


__DATA__
<div id="listSubtitlesFilm">
  <dt id="a1">
    <a href="/45/subtitles-67624.aspx">
      .45 (2006)
    </a>
  </dt>
</div>

输出:

$VAR1 = [
          [
            '.45 (2006)',
            '67624'
          ]
        ];
于 2009-11-07T12:03:46.787 回答
4

代码使用HTML::TreeBuilder

use HTML::TreeBuilder;

my $tree = HTML::TreeBuilder->new_from_content($html);

for my $link ($tree->look_down(
  _tag => 'a', 
  href => qr{/subtitle-\d{2,8}\.aspx})
) {
  my $linkid = $link->attr('href') =~ m!/subtitle-\d{2,8}\.aspx!;
  # Scalar context gets the first, and the first is the nearest parent
  my $parent_div = $link->look_up(_tag => 'div');
  # Now the interesting bit of the link is in $linkid, the parent div ID
  # is $parent_div->id or $parent_div->attr_id, and its text is e.g.
  # $parent_div->as_trimmed_text or you can do other stuff with its content.
}
于 2009-11-07T08:13:40.357 回答
1

get_attr('a1')应该已经读过get_attr('id')了,它会打印“a1”

我认为获取文本内容如下所示:

while ( my $anchor = $parser->get_tag('div') ) {
  my $content = $parser-get_text('/div');
}

或者,如果您的意思是链接的文本内容,它将是:

while ( my $anchor = $parser->get_tag('a') ) {
    if ( my $href = $anchor->get_attr('href') ) {
        my $content = $parser->get_text('/a');
#http://subscene.com/english/Sit-Down-Shut-Up-First-Season/subtitle-272112.aspx
        push @dnldLinks, $1 if $href =~ m!/subtitle-(\d{2,8})\.aspx!;
    }
于 2009-11-07T07:57:28.240 回答
1

您需要在此处更改get_attr("a1")get_attr("id")get_attr (x)正在寻找一个名为 的属性,x但您给它的是属性的值,而不是它的名称。

顺便说一句,<dt>标签不是 a <div>,它是 a <dl>(定义列表)的项目标签。

于 2009-11-07T07:58:20.323 回答