Как искать текст в html-документе с помощью Mechanize?

Я использую WWW::Mechanize, HTML::TreeBuilder и HTML::Element в моем perl-скрипте для навигации по 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"
  • класс "красный"
  • содержание текста "банан"

Тогда мне нужно, чтобы его родитель (<li>-элемент), а от родителя ребенок, текст которого начинается с 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.

1 ответ

Вот psuedocode/ непроверенный 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/;

Это может быть немного чище:

my @elements = $ root-> look_down ('_ tag' => 'div', 'class' => 'red'); foreach my $ e (@elements) {далее, если только $e->as_trimmed_text eq 'Banana'; мой $ e2 = $ e-> right; my ($ shape) = $ e2-> as_trimmed_text = ~ / figure = (. +) /;

     # do something with shape...
  }

WWW:: Механизируйте:: TreeBuilder

Другие вопросы по тегам