Perl HTML :: LinkExtractor在不同的调用上返回不同的链接

时间:2018-05-30 03:07:27

标签: html perl web-scraping text-extraction

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

我传递了相同的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 :(得分:3)

在这一行中,您试图将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之类的运算符,而应将其取消引用为each %$p之类的哈希值。否则,您的代码将无法在最新版本的Perl上运行。