Как я могу найти содержимое div с помощью HTML-модулей Perl, если я знаю тег внутри него?
-
18-09-2019 - |
Вопрос
С тех пор как я спросил, как анализировать html с помощью regex, и меня немного поколотили (и это справедливо), я изучал HTML::Древовидный конструктор, HTML::Синтаксический анализатор, HTML::Разделитель токенов, и HTML::Элементы Модули 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";
}
}
Решение
Для решения вашего конкретного вопроса, учитывая HTML:
<div id="listSubtitlesFilm">
<dt id="a1">
<a href="/45/subtitles-67624.aspx">
.45 (2006)
</a>
</dt>
</div>
Я предполагаю, что вас интересует якорный текст, т. е. ".45 (2006)"
, в данном случае, но только если привязка происходит в div
с удостоверением личности 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' ] ];
Другие советы
Вы могли бы использовать (еще один модуль!) HTML::TreeBuilder::XPath, который, согласно его названию, позволит вам использовать XPath для объектов HTML::TreeBuilder.
#!/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
Код, использующий 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.
}
Вам нужно изменить get_attr("a1")
Для get_attr("id")
вот.В get_attr (x)
ищет атрибут с именем x
, но вы присваиваете ему значение атрибута, а не его имя.
Кстати , тот <dt>
тег - это не <div>
, это тег элемента для <dl>
(список определений).
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!;
}