结果与perl正则表达式混合,匹配html代码中的短语列表

结果与perl正则表达式混合,匹配html代码中的短语列表,html,regex,phrases,Html,Regex,Phrases,结果与正则表达式混合,匹配html代码中的短语列表 这篇新帖子是对另一篇帖子的回应,但由于我不知道的原因,被版主删除了。对我来说,在原始线程中提出这个问题似乎是合乎逻辑的,因为它与尝试使用该线程早期给出的解决方案以及它的问题有关。有一个一般性的参考,似乎没有揭示任何差异,以及信息,“如果你有问题,请发表你自己的问题。”因此这篇文章 我使用LWP::Simple获取网页,然后尝试匹配包含特定短语的行。我在上面提到的线程中复制了regex,并替换/添加了我需要匹配的单词,但是我得到了两个相似但不同的

结果与正则表达式混合,匹配html代码中的短语列表

这篇新帖子是对另一篇帖子的回应,但由于我不知道的原因,被版主删除了。对我来说,在原始线程中提出这个问题似乎是合乎逻辑的,因为它与尝试使用该线程早期给出的解决方案以及它的问题有关。有一个一般性的参考,似乎没有揭示任何差异,以及信息,“如果你有问题,请发表你自己的问题。”因此这篇文章

我使用LWP::Simple获取网页,然后尝试匹配包含特定短语的行。我在上面提到的线程中复制了regex,并替换/添加了我需要匹配的单词,但是我得到了两个相似但不同的网页的混合结果

我使用的正则表达式是:

/^(?=.*?\bYear\b)(?=.*?\bNew Moon\b)(?=.*?\bFirst Quarter\b)(?=.*?\bFull Moon\b)(?=.*?\bLast Quarter\b).*$/gim
对于web站点#1,它有包含这些单词的空行,在一系列由

 Year        New Moon       First Quarter       Full Moon       Last Quarter
但对于网站#2来说,它的文字周围有令人讨厌的小标签:

Year        New Moon       First Quarter       Full Moon       Last Quarter


年新月第一季满月最后一季Δ;T
每一行都匹配

我确信
标记是实现这一点的“正确”方法,但我想知道如何绕过这些标记,以便两个站点都只需要一个正则表达式。有没有一个简单的方法可以做到这一点,或者我必须学习如何解析html(我不想做的事情)


我在寻找一个快速的解决方案,而不是一个稳健的解决方案。这可能只是一次交易。如果这些相对静态的页面发生更改,那么它可能会很小,并且很容易修复。请不要让我参考所有的“html反正则表达式”页面。我见过。请不要让我使用HTML::TreeBuilder。哦,请……

如果我的假设是正确的,您只想匹配特定的单词序列:

<[^>]*?>
具有自由间距,与末端的标记无关

我们可以使用它来匹配任意一端的任何正确格式的开始和结束标记

\s*<[^>]*?>\s*
]*?>
也就是说,任何位于开口“”之间的字符串

接下来,我们要确保在这些标记之间允许有空格,因此我们使用空格指示符“\s*”表示两端的零个或多个空格:

(?:\s*<[^>]*?>\s*)*
\s*]*?>\s*
接下来,我们要将它分组到一个非捕获(为了效率)组中,并让它重复零次或更多次。这是我们将放在正则表达式两端以确保标记匹配的内容:

(?:\s*<[^>]*?>\s*)*\s*Year\s*New Moon\s*First Quarter\s*Full Moon\s*Last Quarter\s*(?:\s*<[^>]*?>\s*)*
(?:\s*]*?>\s*)*
然后,我们将在短语之间使用“\s*”填充所需的文本,以确保它们之间留有空格且仅允许空格:

/^(?:\s*<[^>]*?>\s*)*\s*Year\s*New Moon\s*First Quarter\s*Full Moon\s*Last Quarter\s*(?:\s*<[^>]*?>\s*)*$/gim
(?:\s*]*?>\s*)*\s*年\s*新月\s*第一季度\s*满月\s*最后一季度\s*(?:\s*]*?>\s*)*
然后用线的起点和终点线标记结束

for my $line (split qr/\R/, $doc)
{
    next unless $line =~ /^(?=.*?\bYear\b)(?=.*?\bNew Moon\b)(?=.*?\bFirst Quarter\b)(?=.*?\bFull Moon\b)(?=.*?\bLast Quarter\b).*$/gim; # original
    print "$line\n";
}
/^(?:\s*]*?>\s*)*\s*年\s*新月\s*第一季度\s*满月\s*最后一季度\s*(?:\s*]*?>\s*)*)*$/gim

这应该匹配在所需短语任一端包含任意数量标记的任何行,但如果输入其他任何内容(如附加字符),则不匹配。它也应该是相当有效的,因为它不使用任何环视。如果我误解了这个问题,请告诉我。

我最终通过直接循环检索到的html文档,使用原始正则表达式实现了这两个URL的工作:

my $tree = HTML::TreeBuilder->new;
$tree->parse_file($doc);
my $non_html = $tree->as_text();
open FILE, "<", \$non_html or die "can't open $non_html: $!\n";
这真的不应该这么难

杰克:

嘿,非常感谢。你就是我要找的人。我尝试了它,它与第一个url一起工作,但第二个url没有输出任何内容

使用我原来的正则表达式,我还尝试使用html::TreeBuilder剥离html标记:

my $hs = HTML::Strip->new();
my $clean_text = $hs->parse($doc);
$hs->eof;
open FILE, "<", \$clean_text or die "can't open $clean_text: $!\n";
my$tree=HTML::TreeBuilder->new;
$tree->parse_文件($doc);
我的$non_html=$tree->as_text();

打开文件,“强制性相互参照。你试过使用XML解析器吗?是的,这正是我在文章末尾提到的帖子。我觉得这篇咆哮/宣言真的很有趣,但对我来说没什么帮助。不过我还是从中得到了很多笑声。我确实提到我不想尝试使用HTML::TreeBuilder。不,不,求你了!这是一个perl问题,而不是python问题。我相信这很好,但perl却不行。无论如何都不容易。我试图更改标题,以便不阅读文章第一行的人不会产生歧义,但我不被允许。:)很抱歉,我没有抓到(或误读)perl标记。@MikeM:这正是您所期望的,但事实远非如此。请自行查看:。我正在使用的循环:
while(){下一个除非/^(?=.*\bYear\b)(?=.*\bNew Moon\b)(?=.*\bFirst Quarter\b)(?=.*\bFull Moon\b)(?=.*\bLast Quarter\b)。*$/gim;print;}
my $hs = HTML::Strip->new();
my $clean_text = $hs->parse($doc);
$hs->eof;
open FILE, "<", \$clean_text or die "can't open $clean_text: $!\n";
use strict;
use warnings;
use LWP::Simple;

my $url = 'http://eclipse.gsfc.nasa.gov/phase/phases2001.html';
#my $url = 'http://www.astropixels.com/ephemeris/moon/phases2001gmt.html';
my $doc = get $url;
die "Couldn't get $url" unless defined $doc;
open FILE, "<", \$doc or die "can't open $doc: $!\n";

while(my $line = <FILE>)
{
    #next unless $line =~ /^(?=.*?\bYear\b)(?=.*?\bNew Moon\b)(?=.*?\bFirst Quarter\b)(?=.*?\bFull Moon\b)(?=.*?\bLast Quarter\b).*$/gim; # original
    next unless $line =~ /^(?:\s*<[^>]*?>\s*)*\s*Year\s*New Moon\s*First Quarter\s*Full Moon\s*Last Quarter\s*(?:\s*<[^>]*?>\s*)*$/gim; # Jake's
    print "$line";
}