获取HTML中的特定链接

时间:2013-12-20 20:13:37

标签: html regex perl

精美的Stack Overflow人员。我正在尝试获取HTML文件链接的文件的Perl数组。我对Perl还很新,我对HTML很不熟悉,所以请耐心等待。某些文件标有链接文本的星号(*),,表示文件定期更新。我只想提取定期更新的文件的链接。 HTML文件如下所示:

<tr>
    <td height="34" nowrap width="170">
    <a href="/Files/link1.pdf">Link 1</a>*</td>
</tr>

<!--
<tr>
    <td height="34" nowrap width="170">
    <a href="/Files/link2.pdf">Link 2</a>*</td>
</tr>
-->

<tr>
    <td height="34" nowrap width="170">
    <a href="/Files/link3.pdf">Link 3</a>
    *</td>
</tr>

<tr>
    <td height="34" nowrap width="170">
    <a href="/Files/link4.pdf">Link 4</a></td>
</tr>

所以在我的数组中我想要的是链接1和3的URL,它们用星号标记为更新,但不是2,因为它在注释中而不是4,因为它没有星号。我根据the accepted answer to this question尝试了以下内容:

use strict;
use warnings;
use WWW::Mechanize;

my $page = "file://server/web/site.htm";

my $mech = WWW::Mechanize->new();
$mech->get($page);

my @links = $mech->links();
my @urls;

for my $lnk (@links) {
    push(@urls, $lnk->url);
}

我仍然得到链接#2,即使它在评论中。此外,我不知道从哪里开始只有push带星号的链接,特别是因为链接#3的星号在新行上。我最初尝试使用正则表达式而不使用WWW :: Mechanize,但我无法在下一行获得星号。

use strict;
use warnings;

my $html = do {
    local $/ = undef;
    open(my $fh, "<", "file") || die $!;
    <$fh>;
};

$html =~ s/(<!--)+.*(-->)+//;

my @urls = ($html =~ /\bhref[ ]?=[ ]?"([^"]+)".*\*/gc);

这将获得链接1和2,但不是3.这会在注释中获取链接,因为显然我的查找和替换正则表达式不能正常工作。

那么如何才能获得已加星标的链接并跳过已评论的链接?我对任何想法都持开放态度 - 也许我从一开始就采取的做法是错误的。任何帮助,见解或方向都会很棒。非常感谢你们!

2 个答案:

答案 0 :(得分:2)

在我的示例中,星号表示定期更新的文件,星号位于td标记内。我已经确定了如何使用HTML :: TokeParser提取这些文件。

use strict;
use warnings;
use HTML::TokeParser;

my $html = HTML::TokeParser->new("file.html");

my @urls;

while(my $td = $html->get_tag("td")) {
    my $txt = $html->get_trimmed_text("/td");
    my $url = $html->get_tag("a")->[1]{href};
    if ($txt =~ /\*/) {
        push(@urls, $url);
    }
}

感谢@sabujhassan提供的工作解决方案,感谢@ThisSuitIsBlackNot鼓励我寻求更普遍适用的解决方案。

答案 1 :(得分:1)

根据您的示例,它应该有效。

$html =~ s/<!--.*?-->//sg;
my @urls = ($html =~ /\bhref\s*=\s*"([^"]*)"[^>]*>[^<]*<\/a>\s*\*/sg);
## my @urls = ($html =~ /<a\s+[^>]*href\s*=\s*"([^"]*)"[^>]*>[^<]*<\/a>\s*\*/sg);