Perl HTML :: LinkExtractor возвращает разные ссылки на разные вызовы - PullRequest
0 голосов
/ 30 мая 2018

Я пытаюсь извлечь все изображения из документа HTML (загруженного из Интернета и превращенного в строку (скаляр)), и я использую HTML :: LinkExtractor cpan lib.

IЯ передаю тот же HTML, но извлекаю разные ссылки.

Вопрос: Почему это так и как я могу это исправить?

Код:

my $LX = new HTML::LinkExtractor();
# print($_[0] . "\n\n"); <--- Prints the same HTML document every time
$LX->parse(\$_[0]);

for my $p ( @{$LX->links()} ){
    # Need to iterate though all the
    # values, since images can be hidden
    # in _TEXT w/o any img tag, etc.
    foreach (my( $key, $val ) = each $p) {
        print($key . "--->" . $val . "\n"); <--- Prints different values

Первый выход:

$ ./HTMLPictureScraper.pl http://dustyfeet.com/
/--->/
/--->/
href--->http://dustyfeetonline.com
href--->http://dustyfeetonline.com
target--->_top
target--->_top
href--->http://www.nytimes.com/2006/08/28/technology/28link.html?scp=6&sq=%22stuart%20frankel%22&st=cse
href--->http://www.nytimes.com/2006/08/28/technology/28link.html?scp=6&sq=%22stuart%20frankel%22&st=cse
target--->_top
target--->_top
tag--->a
tag--->a
href--->./evil/evil.html
href--->./evil/evil.html
_TEXT---><a
 href="./pangan/index.html">Warung Seniman</a>
_TEXT---><a
 href="./pangan/index.html">Warung Seniman</a>
href--->./santanyi_registration.html
href--->./santanyi_registration.html
href--->mailto:gecko@dustyfeet.com
href--->mailto:gecko@dustyfeet.com

Второй выход:

$ ./HTMLPictureScraper.pl http://dustyfeet.com/
content--->1vLCRPR1SHmiCICnhWfD7jtpOOSHe79iILqzDkGBUg0=
content--->1vLCRPR1SHmiCICnhWfD7jtpOOSHe79iILqzDkGBUg0=
tag--->a
tag--->a
href--->notuncnj.html
href--->notuncnj.html
tag--->a
tag--->a
tag--->a
tag--->a
tag--->a
tag--->a
tag--->a
tag--->a
tag--->a
tag--->a
tag--->a
tag--->a
href--->mailto:gecko@dustyfeet.com
href--->mailto:gecko@dustyfeet.com

1 Ответ

0 голосов
/ 30 мая 2018

В этой строке вы пытаетесь объединить each -тератор с циклом for-each.Несмотря на их похожие имена, они несовместимы:

foreach (my( $key, $val ) = each $p) {
    print($key . "--->" . $val . "\n");
}

Это получает следующий элемент значения ключа от итератора %$p и назначает список из двух элементов ($key, $val).Затем foreach зацикливается на этих двух элементах.Вот почему вы всегда видите два одинаковых значения дважды.Поскольку порядок итерации с each не определен, вы видите только случайную запись из %$p хеша.

Чтобы исправить это:

Либо используйте цикл while для использованияeach -тератор:

while (my ($key, $val) = each %$p) {
    print "$key--->$val\n";
}

Или используйте цикл foreach для ключей:

for my $key (keys %$p) {
    my $val = $p->{$key};
    print "$key--->$val\n";
}

Я предпочитаю цикл for / foreach, поскольку это позволяет нам сортировать ключив стабильном порядке, вместо того, чтобы полагаться на неопределенный порядок итерации хэша:

for my $key (sort keys %$p) {
    my $val = $p->{$key};
    print "$key--->$val\n";
}

Это должно всегда давать одинаковый вывод для идентичных входных документов.

Как отметил zdim в своем ответеВы не должны передавать скаляры, такие как $p, операторам, таким как keys или each, но должны разыменовывать их в хэш, такой как each %$p.В противном случае ваш код не будет работать на последних версиях Perl.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...