Как искать текст в 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-модуля.


person Hubert Schölnast    schedule 08.06.2015    source источник
comment
Почему вам нужно найти красный банан, а не квадратную фигуру?   -  person Len Jaffe    schedule 08.06.2015
comment
Я ищу более 1000 веб-сайтов для данных. Все они имеют одинаковую структуру. Что такое красный банан в моем упрощенном примере-документе, так это текст исправления и класс исправления, который существует во всех 1000+ документах. Что меняется (и что я пытаюсь извлечь), так это то, что в моем примере квадрат и круг). Вы можете думать о красном + банане как о ключе, а о квадрате как о значении.   -  person Hubert Schölnast    schedule 08.06.2015
comment
Вы можете забыть о WWW::Mechanize и написать только my $root = HTML::TreeBuilder->new_from_url($uri)   -  person Borodin    schedule 09.06.2015


Ответы (1)


вот псевдокод/непроверенный 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 ) { next if $e->as_trimmed_text eq 'Banana'; мой $e2 = $e->право; my ($ shape) = $ e2-> as_trimmed_text =~ /figure = (.+)/;

     # do something with shape...
  }

WWW::Mechanize::TreeBuilder

person Len Jaffe    schedule 08.06.2015
comment
Это очень похоже на обходной путь, который я использую. Но я ожидал более нативного решения, т.е. механизированной команды для поиска текста. - person Hubert Schölnast; 08.06.2015
comment
Явно: я не уверен. Я не нашел явной документации по функции поиска текста. Но я этого не нашел и Его не существует — это две разные вещи, и именно поэтому я должен спросить здесь. - Косвенно: Да. WWW::Mechanize и множество модулей HTML::* охватывают (почти?) все, что связано с разбором html-документов. Вот почему я предполагаю, что в джунглях документации должна быть спрятана функция текстового поиска. Поиск текста в html-документе — обычная задача, поэтому сложно поверить, что разработчики не создали функцию, выполняющую эту задачу. - person Hubert Schölnast; 08.06.2015
comment
Mech в основном связан с навигацией, поэтому основная часть методов имеет дело со ссылками, формами и элементами форм. Вы уже использовали TreeBuilder для синтаксического анализа и запросов HTML, когда простого $content =~ /something/ недостаточно. - person Len Jaffe; 09.06.2015
comment
› Вот почему я предполагаю, что в джунглях должна быть спрятана функция текстового поиска. - person Len Jaffe; 09.06.2015