我遇到了Perl正则表达式的问题。在img
元素上,我希望src
属性与以/file?id
开头的值以及任何class
和alt
属性匹配。我想忽略有时存在的rel
属性,有时不存在,如下所示:
<img rel="lightbox[45451]" src="/file?id=13166" class="bbc_img" alt="myimagess.jpg">
<img src="/file?id=13166" class="bbc_img" alt="myimagess.jpg">
我的问题是如何处理可选的rel
属性。
我正在为rel
属性匹配尝试此操作:
(?!\s+(rel)="([^"]+)")
在没有rel
属性时有效,但在img
具有rel
属性时失败。
答案 0 :(得分:2)
使用正确的HTML解析器这很简单。该计划演示了使用HTML::TreeBuilder
和look_down
方法。
正在搜索所有元素:
src
属性
class
属性(即具有任何值的类属性)alt
属性一旦找到元素,就不会说明你想要做的内容。此代码只使用as_HTML
来显示它们。
use strict;
use warnings;
use HTML::TreeBuilder;
my $html = HTML::TreeBuilder::XPath->new_from_file(\*DATA);
my @images = $html->look_down(
_tag => 'img',
src => qr|^/file\?id=|,
class => qr//,
alt => qr//
);
print $_->as_HTML, "\n" for @images;
__DATA__
<html>
<head>
<title>Page title</title>
</head.
<body>
<img rel="lightbox[45451]" src="/file?id=13166" class="bbc_img" alt="myimagess.jpg">
<img src="/file?id=13166" class="bbc_img" alt="myimagess.jpg">
<img src="/file" class="bbc_img" alt="myimagess.jpg"> /* mismatch id="" */
<img src="/file?id=13166" alt="myimagess.jpg"> /* no class="" */
<img src="/file?id=13166" class="bbc_img"> /* no alt="" */
</body>
</html>
<强>输出强>
<img alt="myimagess.jpg" class="bbc_img" rel="lightbox[45451]" src="/file?id=13166" />
<img alt="myimagess.jpg" class="bbc_img" src="/file?id=13166" />
答案 1 :(得分:2)
Web::Query获胜!
use Web::Query 'wq';
my $html = <<'';
<html>
<img rel="lightbox[45451]" src="/file?id=13166" class="bbc_img" alt="myimagess1.jpg">
<img class="bbc_img" src="/file?id=13167" alt="myimagess2.jpg">
<img src="/file?id=13168" class="bbc_img" >
<img src="/file?id=13169" alt="myimagess3.jpg">
<img src="/foo" class="bbc_img" alt="myimagess.jpg4">
print for wq($html)->find('img[src^="/file?id="][class][alt]')->attr('src');
__END__
/file?id=13166
/file?id=13167
从中学习:XPath比CSS选择器更强大,但CSS选择器更短。
答案 2 :(得分:1)
使用HTML::TreeBuilder::XPath执行此操作的正确方法。这将忽略rel
和任何其他属性,并且不依赖于标记中属性的顺序。
#!/usr/bin/perl
use strict;
use warnings;
use HTML::TreeBuilder::XPath;
use Test::More tests => 1;
my $root= HTML::TreeBuilder::XPath->new_from_content( do { local undef $/; <DATA> });
# this is the important part
my @imgs= $root->findnodes( '//img[starts-with( @src,"/file?id=") and @class and @alt]');
# checks the results
my $hits= join ' ', map { "H:" . src_id( $_->{src}) } @imgs;
is( $hits, 'H:13166 H:13167', "one test");
# shows how to access the attributes
foreach my $img (@imgs)
{ warn "hit: src= $img->{src} - class=$img->{class} - alt: $img->{alt} - id= ", src_id( $img->{src}), "\n"; }
exit;
sub src_id
{ my( $src)= @_;
return $src=~ m{/file\?id=(.+)$} ? $1 : 'no id';
}
__DATA__
<html>
<head><title>Test HTML</title></head.
<body>
<img rel="lightbox[45451]" src="/file?id=13166" class="bbc_img" alt="myimagess1.jpg">
<img class="bbc_img" src="/file?id=13167" alt="myimagess2.jpg">
<img src="/file?id=13168" class="bbc_img" >
<img src="/file?id=13169" alt="myimagess3.jpg">
<img src="/foo" class="bbc_img" alt="myimagess.jpg4">
</body>
</html>