2

我在 perl 脚本中使用 WWW::Mechanize、HTML::TreeBuilder 和 HTML::Element 来浏览 html 文档。

我想知道如何搜索包含某个字符串作为文本的元素。

这是一个 html 文档的示例:

<html>
  <body>
    <ul>
      <li>
       <div class="red">Apple</div>
       <div class="abc">figure = triangle</div>
      </li>
      <li>
       <div class="red">Banana</div>
       <div class="abc">figure = square</div>
      </li>
      <li>
       <div class="green">Lemon</div>
       <div class="abc">figure = circle</div>
      </li>
      <li>
       <div class="blue">Banana</div>
       <div class="abc">figure = line</div>
      </li>
    </ul>
  </body>
</html>

我想提取文本square。要获得它,我必须搜索具有以下属性的元素:

  • 标记名称是“div”
  • 班级是“红色”
  • 内容是文本“香蕉”

然后我需要得到它的父级(a <li>-element),并从父级获取文本以 开头的孩子figure =,但这很容易。

我试过这样:

use strict;
use warnings;
use utf8;
use Encode;
use WWW::Mechanize;
use HTML::TreeBuilder;
use HTML::Element;

binmode STDOUT, ":utf8";

my $mech = WWW::Mechanize->new();

my $uri = 'http.....'; #URI of an existing html-document

$mech->get($uri);
if (($mech->success()) && ($mech->is_html())) {
    my $resp = $mech->response();
    my $cont = $resp->decoded_content;
    my $root = HTML::TreeBuilder->new_from_content($cont);

    #this works, but returns 2 elements:
    my @twoElements = $root->look_down('_tag' => 'div', 'class' => 'red');

    #this returns an empty list:
    my @empty = $root->look_down('_tag' => 'div', 'class' => 'red', '_content' => 'Banana');

    # do something with @twoElements or @empty   
}

我必须使用什么来代替最后一个命令来获取想要的元素?

我不是在寻找解决方法(我找到了)。我想要的是 WWW::Mechanize、HTML::Tree 或任何其他 cpan-modul 的本机功能。

4

1 回答 1

0

这是伪代码/未经测试的 Perl:

  my @twoElements = $root->look_down('_tag' => 'div', 'class' => 'red');
  foreach my $e ( @twoElements ) {
     next unless $e->content_list->[0] eq 'Banana';
     my $e2 = $e->right;   # get the sibling - might need to try left() depending on ordering
     my ($shape) = $e2->content_list->[0] =~ /figure = (.+)/;

     # do something with shape...

  }

不完美,但它应该让你开始,而且它足够通用,可以轻松重用。否则替换

    ($shape) = $e2->content_list->[0] =~ /figure = (.+)/;

有类似的东西

$shape = 'square' if $e2->content_list->[0] =~ /square/;

这可能会更干净一点:

我的@elements = $root->look_down('_tag' => 'div', 'class' => 'red' ); foreach my $e (@elements) { next 除非 $e->as_trimmed_text eq 'Banana'; 我的 $e2 = $e-> 对;我的 ($shape) = $e2->as_trimmed_text =~ /figure = (.+)/;

     # do something with shape...
  }

WWW::Mechanize::TreeBuilder

于 2015-06-08T17:26:53.947 回答