2012-11-27 69 views
1

我不是Perl专家,但我已经写了一个Perl脚本所有href标签来解析HTML页面和过滤:如何从Perl中的HTML页面上的链接中提取文本?

输出如下所示:

href="?Name">Name</a> 
href="?Desc">Hourly Details</a> 
href="/24x7/2012/11-November/">Data 
href="./00:00:00/">00:00:00/</a> 
href="./01:00:00/">01:00:00/</a> 
href="./02:00:00/">02:00:00/</a> 
href="./03:00:00/">03:00:00/</a> 
href="./04:00:00/">04:00:00/</a> 
href="./05:00:00/">05:00:00/</a> 
href="./06:00:00/">06:00:00/</a> 
href="./07:00:00/">07:00:00/</a> 
href="./08:00:00/">08:00:00/</a> 
href="./09:00:00/">09:00:00/</a> 
href="./10:00:00/">10:00:00/</a> 
href="./11:00:00/">11:00:00/</a> 
href="./12:00:00/">12:00:00/</a> 
href="./13:00:00/">13:00:00/</a> 
href="./14:00:00/">14:00:00/</a> 
href="./15:00:00/">15:00:00/</a> 
href="./16:00:00/">16:00:00/</a> 
href="./17:00:00/">17:00:00/</a> 
href="./18:00:00/">18:00:00/</a> 
href="./19:00:00/">19:00:00/</a> 
href="./20:00:00/">20:00:00/</a> 
href="./21:00:00/">21:00:00/</a> 
href="./22:00:00/">22:00:00/</a> 
href="./23:00:00/">23:00:00/</a> 

现在我想从“00:00:00”到“23:00:00”提取href标签内的值,同时排除其他值。通过尝试下面的代码

http://x.download.com/00:00:00 
------URL------------/..href../ 
.............................. 
http://x.download.com/23:00:00 

但是:

foreach (@tag) { 
    if (m/href/) { 
     if ($_ =~ /"\/24/ && $_ =~ /"\/[0-9]/) { 
      my $href = $_; 
      my $start = index($href, "\""); 
      my $end = rindex($href, "\""); 
      my $link = substr($href, $start + 1, $end - $start - 1); 
      print "Follow: " . $url . $link . "\n"; 

     } 
    } 
} 

打印:

Follow: http://x.download.com/24x7/2012/11-November/ 

我应该我的正则表达式是这样的结果值将被添加到字符串有一个网址要求的目标可以实现?

回答

3

这是用一个正则表达式完成的,如下面的程序所示。它会在>之后立即查找一串数字或冒号(因此会查找元素的文本内容而不是像您的那样查找href属性值),并将该字符串捕获到$1

但我宁愿看到从开始解决使用适当的HTML解析器来完成的问题,如 HTML::TreeBuilderMojo::DOM

use strict; 
use warnings; 

my @tag = <DATA>; 

foreach (@tag) { 
    next unless />([\d:]+)/; 
    print "http://x.download.com/$1\n"; 
} 

__DATA__ 
href="?Name">Name</a> 
href="?Desc">Hourly Details</a> 
href="/24x7/2012/11-November/">Data 
href="./00:00:00/">00:00:00/</a> 
href="./01:00:00/">01:00:00/</a> 
href="./02:00:00/">02:00:00/</a> 
href="./03:00:00/">03:00:00/</a> 
href="./04:00:00/">04:00:00/</a> 
href="./05:00:00/">05:00:00/</a> 
href="./06:00:00/">06:00:00/</a> 
href="./07:00:00/">07:00:00/</a> 
href="./08:00:00/">08:00:00/</a> 
href="./09:00:00/">09:00:00/</a> 
href="./10:00:00/">10:00:00/</a> 

输出

http://x.download.com/00:00:00 
http://x.download.com/01:00:00 
http://x.download.com/02:00:00 
http://x.download.com/03:00:00 
http://x.download.com/04:00:00 
http://x.download.com/05:00:00 
http://x.download.com/06:00:00 
http://x.download.com/07:00:00 
http://x.download.com/08:00:00 
http://x.download.com/09:00:00 
http://x.download.com/10:00:00 
+0

对不起,你可以提供什么,我应该使用的情况下在while循环 - 我在程序中出现错误。如果你可以像上面例子那样使用@tag变量会很有帮助 – Prakash

+0

我使用了'DATA',这样我就可以将示例数据包含在Perl源代码中。我已经修改了我的解决方案,以便在处理它之前将数据读入'@ tag',如您所请求的 – Borodin

0

首先,我们需要指定一个正则表达式将捕获的军事倍至第二位。

my $regex 
    = qr{ # curly brackets instead of slashes 
      # so that we can use literal slashes in expression 

    " # a quote 
    \. # a literal dot 
    / # a forward slash 
    ( # begin capture group 

     (?:    # begin uncaptured sub-group 
      [01] \d  # a '0' or '1' followed by a digit 
     | 2 [0-3] # a '2' followed by 0-3 
     )    # end grouping 
     (?:   # begin repetition grouping 
     :   # a literal colon    
     [0-5] \d # digits 0-5 followed by any digit 
     ){2}  # exactly twice 
    ) # end capture 

    /# a forward slash 
    " # close quote 
}x; # <- x-option allows annotated regex 
... 

这等同于以下的正则表达式:

my $regex = qr/"\.\/((?:[01]\d|2[0-3])(:[0-5]\d){2})\/"/; 

如果你的分和秒将永远只能是'00:00' ,则表达式更容易:

my $regex = qr{"\./((?:[01]\d|2[0-3]):00:00)/"}; 

然后您可以测试通过在列表中进行匹配来检索该值上下文:

if (my ($link) = m/$regex/) { 
    say "http://x.download.com/$link"; 
} 

如果测试不符合,$link将不确定。如果匹配,将其声明为一个(一个)列表,则匹配操作会将第一个捕获分配给该变量。

+0

谢谢,但我得到的最终链接如下:http://x.download.com./23:00:00/ - 注意http://x.download.com – Prakash

+0

@Prakash后的额外点,我认为这将是您的提取代码,我没有更改,但在下一个版本中,我添加了我的提取代码。在捕获正则表达式中指定要跳过的内容会更好。 – Axeman

+0

感谢您提供的解释和示例。我确实看到预期的输出按照每个问题的要求 – Prakash

3

你不想用正则表达式来做。您需要一个正确的HTML解析器,而正则表达式无法完成这项工作。

如何提取网页?如果您使用的是WWW :: Mechanize,那么从您提取的页面中提取链接是一个方法调用,因为WWW :: Mechanize会为您执行HTML解析。

use WWW::Mechanize; 

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

my @links = $mech->links(); 
for my $link (@links) { 
    say $link->text, ' -> ', $link->url; # Show the text and the URL 
} 

你需要重新格式化,只要你认为合适,但是这给了你一个想法。

+0

我正在使用$ browser-> get($ url);获取网页,然后$ contents = $ response-> content; my @breakup = split('',$ contents);获取页面内容 – Prakash

+0

'$ browser'是什么?你用什么班级来做'get'? –

+0

我正在使用LWP lib来获取网页。使用LWP :: Simple;我的$浏览器; $ browser-> get($ url);获取网页,然后$ contents = $ response-> content; my @breakup = split('',$ contents);获取页面内容 – Prakash

相关问题