如何使用Perl从字符串中去除HTML?

12

使用Perl从字符串中剥离HTML,是否有比这更简单的方法?

$Error_Msg =~ s|<b>||ig;
$Error_Msg =~ s|</b>||ig;
$Error_Msg =~ s|<h1>||ig;
$Error_Msg =~ s|</h1>||ig;
$Error_Msg =~ s|<br>||ig;

我希望能有一个简化的正则表达式,例如像这样:

$Error_Msg =~ s|</?[b|h1|br]>||ig;

是否存在一个现有的Perl函数可以从字符串中去除任何/所有HTML,即使我只需要去除粗体、h1标题和br标签?

3个回答

25

假设代码是有效的HTML(没有漫游的<或>运算符)

$htmlCode =~ s|<.+?>||g;

如果你只需要移除粗体、h1和br标签

$htmlCode =~ s#</?(?:b|h1|br)\b.*?>##g

而且你可能想考虑使用HTML::Strip模块。


6
我不会说“可能”,我会说“应该”。在当今时代,试图使用正则表达式来清除HTML是荒谬的。从CPAN中使用众多HTML清理模块之一,最好选择一个旨在防止XSS漏洞且非Daniel Muey编写的模块。 - nothingmuch
3
注意,HTML::Strip 不正确地支持 UTF-8 编码的字符串。请查看此处的解决方法:https://gist.github.com/910818 - nick

16

perlfaq9: 如何从字符串中删除HTML?


最正确的方法(虽然不是最快的)是使用来自CPAN的HTML::Parser。另一种大多数情况下正确的方法是使用HTML::FormatText,它不仅删除HTML,还尝试对生成的纯文本进行简单的格式化。

许多人尝试使用简单的正则表达式方法,例如s/<.*?>//g,但在许多情况下会失败,因为标记可能继续跨越换行符,它们可能包含带引号的尖括号,或者可能存在HTML注释。此外,人们忘记转换实体-例如<。

这里是一个“简单”的方法,适用于大多数文件:

#!/usr/bin/perl -p0777
s/<(?:[^>'"]*|(['"]).*?\1)*>//gs

如果您需要更全面的解决方案,请参考http://www.cpan.org/authors/id/T/TO/TOMC/scripts/striphtml.gz中的三阶段striphtml程序。
以下是一些你在选择解决方案时应该考虑的棘手情况:
<IMG SRC = "foo.gif" ALT = "A > B">

<IMG SRC = "foo.gif"
 ALT = "A > B">

<!-- <A comment> -->

<script>if (a<b && a>c)</script>

<# Just data #>

<![INCLUDE CDATA [ >>>>>>>>>>>> ]]>

如果HTML注释包含其他标记,则这些解决方案也会在类似于此文本的文本中出现问题:
<!-- This section commented out.
    <B>You can't see me!</B>
-->

关于您的脚本建议--http://www.cpan.org/authors/id/T/TO/TOMC/scripts/striphtml.gz--这将删除所有内容。我该如何修改此代码,仅保留特定的HTML标签?除此之外,它运行良好。 - PKHunter

16

你应该一定要看看HTML::Restrict,它可以让你剥离或限制允许的HTML标签。一个最小的示例,它会剥离所有HTML标签:

use HTML::Restrict;

my $hr = HTML::Restrict->new();
my $processed = $hr->process('<b>i am bold</b>'); # returns 'i am bold'

我建议远离HTML::Strip,因为它会破坏utf8编码


它不支持Perl 5.8.x。这是一个超级程序,但了解它的支持结构会很好。 - PKHunter
我也不确定是否有一种方法可以保留没有开放和关闭标签的标记(可允许的标记)。例如,'<br/>' 很难识别。 - PKHunter

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接