在Java中剥离HTML标签[重复]

Posted

技术标签:

【中文标题】在Java中剥离HTML标签[重复]【英文标题】:Stripping HTML tags in Java [duplicate] 【发布时间】:2010-10-24 08:59:30 【问题描述】:

是否有现有的 Java 库提供从字符串中去除所有 html 标记的方法?我正在寻找与 php 中的 strip_tags 函数等效的东西。

我知道我可以使用this *** question 中描述的正则表达式,但是我很好奇是否已经有一个 stripTags() 方法可以在 Apache Commons 库中的某个地方使用。

【问题讨论】:

与此同时,我正在使用以下代码从字符串中删除所有 HTML 标记: String strippedHtml = rawHtml.replaceAll("", ""); 【参考方案1】:

使用JSoup,它有很好的文档记录,可以在 Maven 上使用,并且在花了一天时间使用几个库之后,对我来说,这是我能想象到的最好的一个。我自己的意见是,这样的工作,将 html 解析为纯文本,应该可以在一行代码中 - >否则库以某种方式失败......只是说 ^^ 所以这就是 JSoup 的单行 - 在 Markdown4J 中,类似的东西不是有可能,在 Markdownj 中也是如此,在 htmlCleaner 中,大约 50 行代码真是让人头疼……

String plain = new HtmlToPlainText().getPlainText(Jsoup.parse(html));

你得到的是真正的纯文本(不仅仅是作为字符串的 html 源代码,就像在其他库中一样)-> 他在这方面做得很好。它的质量与 PHP 的 Markdownify 或多或少相同......

【讨论】:

Jsoup 的问题在于它还会删除新行,因此所有解析的输入都将在一行上。 如果输入包含“%gt;tag<”,结果可以包含HTML标签或类似的。 好的 Jules 但是这不是 JSoup 的问题..其他人在这方面更好吗?没关系,因为在将他提供给 JSoup 之前简单地解码 url 编码的 html 字符串对我来说感觉更好,而不是编写几行代码来实现 JSoup 的功能(如果这里的另一个库会更好的话)特别的东西) @johnflan 不仅将换行符转换为空格,还将某些空格转换为换行符!尚未查看源代码,但如果您有一个由单个空格组成的TextNode,这似乎会发生。我不知道这背后的逻辑,但正如 HtmlToPlainText 的 Javadoc 中所说,“请注意,这是一个相当简单的格式化程序——对于现实世界的使用,你会想要接受和扩展。” 可能HtmlToPlainText 来自旧版本。现在只是Jsoup.parse(html).text()【参考方案2】:

这是我在谷歌上找到的。 对我来说效果很好。

String noHTMLString = htmlString.replaceAll("\\<.*?\\>", "");

【讨论】:

这不会删除像 这样的非 html 标签吗? 我不相信像这样的简短正则表达式 可以 涵盖所有 html 情况......特殊格式是什么?像 JSoup 这样的优秀库在生成纯文本(!)时甚至会关心格式......我的意思是,转换,你永远不会只使用正则表达式来实现这一点 我建议添加 < >标签也是。字符串 noHTMLString = htmlString.replaceAll("(\\<.>|<.*?>)", "");顺便说一句,它删除了像 这样的非 html 标签 并且,作为警告,您应该始终牢记 Stack Overflow 上最具传奇色彩的答案之一:***.com/a/1732454/256788【参考方案3】:

无论您做什么,请确保在开始尝试剥离标签之前对数据进行规范化。我最近参加了一个涵盖 XSS 过滤器规避的 Web 应用安全研讨会。人们通常会认为搜索&amp;lt;&amp;lt; 或其十六进制等效项就足够了。在看到一张幻灯片后,我被震撼了,其中包含 70 种 &amp;lt; 可以被编码以击败过滤器的方式。

更新:

下面是我提到的演示文稿,请参阅幻灯片 26 了解编码 &amp;lt; 的 70 种方法。

Filter Evasion: Houdini on the Wire

【讨论】:

能否请您添加该幻灯片的链接?我相信没有多少编码方法对浏览器有效... 如果我错了,请纠正我,但这个列表中的第一项不是浏览器实际解释为开始 HTML 标记的唯一一项吗?其余的要么按原样显示,要么在结果文档中显示为文字“ 【参考方案4】:

可能有一些,但最强大的是使用实际的 HTML 解析器。有一个here,如果格式合理,您还可以使用 SAX 或其他 XML 解析器。

【讨论】:

当然,如果你最终想要得到的是一个可以保证安全地包含在 HTML 输出中的字符串,那么 HTML 解析器不是你想要的,否则字符串 '&lt ;脚本>警报(“你好”);'将通过解析器并最终变得危险,即使它不是从...开始的...... 也许如果你能停止居高临下,它会更有用。我对 HTML 解析器非常熟悉,并且在过去 20 年中使用过很多。通常,HTML 解析器的输出将是一个 DOM 或类似的东西,但问题显然要求一个字符串,所以我假设您的建议是使用生成的解析 DOM 的 W3C DOM 属性textContent,或者如果使用输出不是 DOM 的解析器,则某些等价物。如果这是您推荐的,这是危险的,因为如果 HTML 内容在源文档中编码为实体,它将允许通过。 也许吧。也许不是。但是,如果您对“解析器”的概念不清楚,我不会打赌。 @Jules, '<script>alert("hello");'将通过解析器并作为文本节点从另一端出来,文本内容为'【参考方案5】:

在提出这个问题将近一周后,我可以肯定地说,Java API 或 Apache 库中没有可用的方法从字符串中去除 HTML 标记。您要么必须使用前面答案中描述的 HTML 解析器,要么编写一个简单的正则表达式来去除标签。

【讨论】:

嗯,如果不是 HTML 解析器,您认为会做这样的事情吗?或者,就此而言,您认为您正在使用正则表达式做什么? 我想他对正则表达式所做的事情与我对正则表达式所做的事情相同:从字符串中删除任何看起来好像是 HTML 标记的内容,以确保生成的字符串 (1) 是人类可读的,并且 (2) 如果嵌入网页中不会导致 XSS 漏洞。【参考方案6】:

当使用 Jsoup 时,它甚至比上述答案中描述的更容易:

String html = "bla <b>hehe</b> <br> this is awesome simple";

String text = Jsoup.parse(html).text();

【讨论】:

这对我有用,似乎与 Jsoup 将空格转换为换行符(TextNode 仅包含空格)或换行符转换为空格(正常的 Jsoup 行为)无关,这似乎是new HtmlToPlainText().getPlainText( Jsoup.parse( htmlHitLine ));的问题 很高兴听到这个消息:))【参考方案7】:

我使用nekoHtml 来做到这一点。它可以去除所有标签,但也可以轻松保留或去除标签子集。

【讨论】:

【参考方案8】:

我知道这个问题很老了,但是我也一直在找这个问题,似乎在java中找到一个好的简单的解决方案仍然不容易。

今天我遇到了这个小函数库。它实际上是在试图模仿php的strip_tags函数。

http://jmelo.lyncode.com/java-strip_tags-php-function/

它的工作原理是这样的(从他们的网站复制):

    import static com.lyncode.jtwig.functions.util.HtmlUtils.stripTags;

    public class StripTagsExample 
      public static void main(String... args) 
        String result = stripTags("<!-- <a href='test'></a>--><a>Test</a>", "");
        // Produced result: Test
      
    

【讨论】:

【参考方案9】:

您好,我知道这个帖子很旧,但它仍然在 Google 上名列前茅,我正在寻找解决相同问题的快速方法。找不到任何有用的东西,所以我想出了这个代码 sn-p - 希望它对某人有所帮助。它只是循环字符串并跳过所有标签。简单明了。

boolean intag = false;
String inp = "<H1>Some <b>HTML</b> <span style=blablabla>text</span>";
String outp = "";

for (int i=0; i < inp.length(); ++i)

    if (!intag && inp.charAt(i) == '<')
        
            intag = true;
            continue;
        
        if (intag && inp.charAt(i) == '>')
        
            intag = false;
            continue;
        
        if (!intag)
        
            outp = outp + inp.charAt(i);
        
   
return outp;

【讨论】:

您可以考虑使用 StringBuilder 作为输出。您将如何处理格式错误的 HTML?如果我的 HTML 包含未转义的小于或大于字符怎么办?【参考方案10】:

采用纯迭代方法,没有正则表达式:

public String stripTags(final String html) 

    final StringBuilder sbText = new StringBuilder(1000);
    final StringBuilder sbHtml = new StringBuilder(1000);

    boolean isText = true;

    for (char ch : html.toCharArray()) 
        if (isText)  // outside html
            if (ch != '<') 
                sbText.append(ch);
                continue;
             else    // switch mode             
                isText = false;      
                sbHtml.append(ch); 
                continue;
            
        else  // inside html
            if (ch != '>') 
                sbHtml.append(ch);
                continue;
             else       // switch mode    
                isText = true;     
                sbHtml.append(ch); 
                continue;
            
        
    

    return sbText.toString();

【讨论】:

【参考方案11】:

由于html片段的缩写(字符串截断),我也遇到了正则表达式无法检测到的未闭合html标签的问题。 例如:

Lorem ipsum dolor sit amet, <b>consectetur</b> adipiscing elit. <a href="abc"

所以,参考 2 个最佳答案(JSoup 和正则表达式),我更喜欢使用 JSoup 的解决方案:

Jsoup.parse(html).text()

【讨论】:

【参考方案12】:

Wicket 使用以下方法转义 html,位于:org.apache.wicket.util.string.Strings

public static CharSequence escapeMarkup(final String s, final boolean escapeSpaces,
    final boolean convertToHtmlUnicodeEscapes)

    if (s == null)
    
        return null;
    
    else
    
        int len = s.length();
        final AppendingStringBuffer buffer = new AppendingStringBuffer((int)(len * 1.1));

        for (int i = 0; i < len; i++)
        
            final char c = s.charAt(i);

            switch (c)
            
                case '\t' :
                    if (escapeSpaces)
                    
                        // Assumption is four space tabs (sorry, but that's
                        // just how it is!)
                        buffer.append("&nbsp;&nbsp;&nbsp;&nbsp;");
                    
                    else
                    
                        buffer.append(c);
                    
                    break;

                case ' ' :
                    if (escapeSpaces)
                    
                        buffer.append("&nbsp;");
                    
                    else
                    
                        buffer.append(c);
                    
                    break;

                case '<' :
                    buffer.append("&lt;");
                    break;

                case '>' :
                    buffer.append("&gt;");
                    break;

                case '&' :

                    buffer.append("&amp;");
                    break;

                case '"' :
                    buffer.append("&quot;");
                    break;

                case '\'' :
                    buffer.append("&#039;");
                    break;

                default :

                    if (convertToHtmlUnicodeEscapes)
                    
                        int ci = 0xffff & c;
                        if (ci < 160)
                        
                            // nothing special only 7 Bit
                            buffer.append(c);
                        
                        else
                        
                            // Not 7 Bit use the unicode system
                            buffer.append("&#");
                            buffer.append(new Integer(ci).toString());
                            buffer.append(';');
                        
                    
                    else
                    
                        buffer.append(c);
                    

                    break;
            
        

        return buffer;
    

【讨论】:

这是转义,不是剥离 没错,这两者是有区别的!【参考方案13】:
public static String stripTags(String str) 
    int startPosition = str.indexOf('<');
    int endPosition;
    while (startPosition != -1) 
        endPosition = str.indexOf('>', startPosition);
        str = str.substring(0, startPosition) + (endPosition != -1 ? str.substring(endPosition + 1) : "");
        startPosition = str.indexOf('<');
    
    return str;

【讨论】:

以上是关于在Java中剥离HTML标签[重复]的主要内容,如果未能解决你的问题,请参考以下文章

如何防止 Wordpress 在摘录中剥离 HTML 标签

在 python 中使用 mechanize 剥离 html 标签并仅返回文本

PHP DOM获取nodevalue html? (不剥离标签)

PHP nodevalue剥离html标签

如何使用标签的 id 剥离标签及其所有内部 html?

如何使用标签的ID剥离标签及其所有内部html?