Perl HTML::LinkExtractor returns 不同调用的不同链接

Perl HTML::LinkExtractor returns different links on different calls

我正在尝试从 HTML 文档中提取所有图像(从网上下载并转换为字符串(标量)),并且我正在使用 HTML::LinkExtractor cpan 库。

我传递相同的 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

在这一行中,您尝试将 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 之类的标量传递给 keyseach 之类的运算符,而应该将其取消引用到 [=24= 这样的哈希].否则,您的代码将无法在最新版本的 Perl 上运行。