Как разобрать HTML с HTML::TreeBuilder?

Это код, который я хотел бы разобрать

[...]
<div class="item" style="clear:left;">
 <div class="icon" style="background-image:url(http://nwn2db.com/assets/builder/icons/40x40/is_acidsplash.png);">
 </div>
  <h2>Acid Splash</h2>
   <p>Caster Level(s): Wizard / Sorcerer 0
   <br />Innate Level: 0
   <br />School: Conjuration
   <br />Descriptor(s): Acid
   <br />Component(s): Verbal, Somatic
   <br />Range: Medium
   <br />Area of Effect / Target: Single
   <br />Duration: Instant
   <br />Save: None
   <br />Spell Resistance: Yes
   <p>
   You fire a small orb of acid at the target for 1d3 points of acid damage.
 </div>
[...]

Это мой алгоритм:

my $text = '';

scan_child($spells);

print $text, "\n";

sub scan_child {
  my $element = $_[0];
  return if ($element->tag eq 'script' or
             $element->tag eq 'a');   # prune!
  foreach my $child ($element->content_list) {
    if (ref $child) {  # it's an element
      scan_child($child);  # recurse!
    } else {           # it's a text node!
      $child =~ s/(.*)\:/\\item \[$1\]/; #itemize
      $text .= $child;
      $text .= "\n";
    }
   }
  return;
}

Это получает образец <key> : <value> и чернослив мусор как <script> или же <a>...</a>, Я хотел бы улучшить его, чтобы получить <h2>...</h2> заголовок и все <p>...<p> блок, чтобы я мог добавить некоторые теги LaTeX.

Любая подсказка?

Заранее спасибо.

2 ответа

Я использую look_down() метод сканирования HTML. С помощью look_down() Я могу вернуть сначала получить список всех div'ов class="item".

Затем я могу выполнить их итерацию, найти и обработать h2 и p, который я тогда разделил бы, используя // как мой сплиттер.

Потому что это может быть проблема XY...

Mojo::DOM является несколько более современной средой для анализа HTML с использованием селекторов CSS. Следующее извлекает нужный элемент P из документа:

use strict;
use warnings;

use Mojo::DOM;

my $dom = Mojo::DOM->new(do {local $/; <DATA>});

for my $h2 ($dom->find('h2')->each) {
    next unless $h2->all_text eq 'Acid Splash';

    # Get following P
    my $next_p = $h2;
    while ($next_p = $next_p->next_sibling()) {
        last if $next_p->node eq 'tag' and $next_p->type eq 'p';
    }

    print $next_p;
}

__DATA__
<html>
<body>
<div class="item" style="clear:left;">
 <div class="icon" style="background-image:url(http://nwn2db.com/assets/builder/icons/40x40/is_acidsplash.png);">
 </div>
  <h2>Acid Splash</h2>
   <p>Caster Level(s): Wizard / Sorcerer 0
   <br />Innate Level: 0
   <br />School: Conjuration
   <br />Descriptor(s): Acid
   <br />Component(s): Verbal, Somatic
   <br />Range: Medium
   <br />Area of Effect / Target: Single
   <br />Duration: Instant
   <br />Save: None
   <br />Spell Resistance: Yes
   <p>
   You fire a small orb of acid at the target for 1d3 points of acid damage.
 </div>
 </body>
 </html>

Выходы:

<p>Caster Level(s): Wizard / Sorcerer 0
   <br>Innate Level: 0
   <br>School: Conjuration
   <br>Descriptor(s): Acid
   <br>Component(s): Verbal, Somatic
   <br>Range: Medium
   <br>Area of Effect / Target: Single
   <br>Duration: Instant
   <br>Save: None
   <br>Spell Resistance: Yes
   </p>
Другие вопросы по тегам