用正则表达式解析 HTML 是个坏主意,但它似乎适合这种情况。
描述:给定一个 .html 文件,我必须解析内部链接,提取缩进级别、链接文本和它所在的页码到外部 .txt 文件,然后传递给其他人。
给定这个示例 HTML:
<TR valign="bottom">
<TD valign="top"><DIV style="margin-left:0px; text-indent:-0px"><A href="#101"><FONT style="font-variant:small-caps;">The “Offering“</FONT>
</A></DIV></TD>
<TD> </TD>
<TD nowrap align="right" valign="top"> </TD>
<TD align="right" valign="top">1</TD>
<TD nowrap valign="top"> </TD>
</TR>
<TR valign="bottom">
<TD valign="top"><DIV style="margin-left:15px; text-indent:-0px"><A href="#102">Sales & Property
</A></DIV></TD>
<TD> </TD>
<TD nowrap align="right" valign="top"> </TD>
<TD align="right" valign="top">2</TD>
<TD nowrap valign="top"> </TD>
</TR>
外部文件将产生:
0|The "Offering"|4
15|Sales & Property|5
(页码不同,因为它们是实际页码,而不是作品集引用)。
除了 1 部分,我已经弄清楚了,当链接的文本包含额外的 HTML 代码时,比如 <Font>
在第一个链接中标记。
这是我提取链接的正则表达式(注意 $string 包含上面的 html):
while ($string =~ m/<DIV style="margin-left:([0-9]+)px; text-indent:[-0-9]+px"><A href="#([0-9]+)">([a-zA-Z0-9\.,:;&#\s]+)<\/A>/gi) {
push(@indents,$1);
push(@linkIDs,$2);
push(@names,escapeHTML($3));
};
这将正确提取第二个,但不是第一个,因为 HTML 代码中有 >< 和其他符号。
如果我将最后一个捕获组更改为 .+
或 .*
,我得到了整个 HTML 文件(好吧,在第一个 <Div><A>
和最后一个 </A>
之间。似乎模式是从开头开始的,但是从文件末尾向后匹配。
这是在线正则表达式构建器的链接:http://regexr.com?2s0po
它正确地找到了我需要的东西,但在 Perl 中我没有得到相同的结果(只是提到的整个文件)。
我似乎无法写出任何能够正确捕获每个组的内容 - 你会认为“光标”会向前移动并停在第一个 </A>
处它从文件的开头看到。
任何帮助或意见或指导将不胜感激。 -谢谢。
最佳答案
在解析 HTML 或类似结构时,您必须小心使用正则表达式。您尝试的正则表达式有两个问题:
- 嵌套标签(第一个条目中的字体标签)
- 换行符(在第一个结束 anchor 标记之前)
这是处理这些问题的正则表达式:
use HTML::Entities;
while ($string =~ m/<DIV style="margin-left:([0-9]+)px; text-indent:[-0-9]+px"><A href="#([0-9]+)">(.*?)<\/A>/gis) {
my $indent = $1;
my $page = $2;
(my $name = $3) =~ s/\s+$//;
$name =~ s/^\s+//;
$name =~ s/<.*?>//g;
print $indent, '|', decode_entities($name), '|', $page, "\n";
}
关于html - Perl 正则表达式仅向前解析;不是从头到尾,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3535919/