【问题标题】:regular expression to extract text from HTML从 HTML 中提取文本的正则表达式
【发布时间】:2010-09-15 21:59:52
【问题描述】:

我想从一般 HTML 页面中提取所有文本(显示或不显示)。

我想删除

  • 任何 HTML 标签
  • 任何javascript
  • 任何 CSS 样式

是否有一个正则表达式(一个或多个)可以实现这一目标?

【问题讨论】:

标签: html regex html-content-extraction text-extraction


【解决方案1】:

删除 javascript 和 CSS:

<(script|style).*?</\1>

删除标签

<.*?>

【讨论】:

  • //g 会带你去天堂之城。
  • 谢谢,这真的简化了一切!
【解决方案2】:

您无法真正使用正则表达式解析 HTML。这太复杂了。 RE 根本无法正确处理 &lt;![CDATA[ 部分。此外,诸如&amp;lt;text&gt; 之类的一些常见 HTML 内容将在浏览器中作为正确的文本工作,但可能会使天真的 RE 感到困惑。

使用合适的 HTML 解析器会让您更快乐、更成功。 Python 人经常使用 Beautiful Soup 来解析 HTML 并去除标签和脚本。


此外,浏览器在设计上允许格式错误的 HTML。因此,您经常会发现自己试图解析显然不正确的 HTML,但在浏览器中却可以正常工作。

您也许可以使用 RE 解析错误的 HTML。它所需要的只是耐心和努力工作。但使用别人的解析器通常更简单。

【讨论】:

  • 一定要使用专门的 HTML 解析器——不要自己动手!如果您使用 Ruby,我只是想建议 Hpricot。
  • 为什么要 困扰 RE?大多数只是设置为忽略它,这是正确的:它是文本,而不是 HTML。如果是因为他们解析 HTML 实体(我想这是个好主意),你应该在你的 RE 之后的文本上这样做,而不是在 HTML 上......
  • @monoxide:我的意思不是说不可能。我的观点是,您可以通过使用其他人的能够正确处理所有边缘情况的解析器来节省大量的 RE 调试。
  • +1 但我认为关于格式错误的 HTML 的观点在这里无关紧要,因为我们特别不尝试解析 HTML 有一个正则表达式是可以的,它只是拉出任何看起来像标签的东西,不管结构。
  • @annakata:“提取任何看起来像标签的东西”或多或少是在解析。因为 HTML 是一种比 RE 设计描述的更复杂的语言,所以解析是在 HTML 中查找任何内容的唯一方法。除非在微不足道的情况下,否则 RE 总是被击败。
【解决方案3】:

需要一个正则表达式解决方案(在 php 中),它可以返回与 PHPSimpleDOM 一样(或更好)的纯文本,只是要快得多。这是我想出的解决方案:

function plaintext($html)
{
    // remove comments and any content found in the the comment area (strip_tags only removes the actual tags).
    $plaintext = preg_replace('#<!--.*?-->#s', '', $html);

    // put a space between list items (strip_tags just removes the tags).
    $plaintext = preg_replace('#</li>#', ' </li>', $plaintext);

    // remove all script and style tags
    $plaintext = preg_replace('#<(script|style)\b[^>]*>(.*?)</(script|style)>#is', "", $plaintext);

    // remove br tags (missed by strip_tags)
    $plaintext = preg_replace("#<br[^>]*?>#", " ", $plaintext);

    // remove all remaining html
    $plaintext = strip_tags($plaintext);

    return $plaintext;
}

当我在一些复杂的网站(论坛似乎包含一些更难解析的 html)上测试这个时,这个方法返回了与 PHPSimpleDOM 纯文本相同的结果,只是快得多。它还正确处理了列表项(li 标签),而 PHPSimpleDOM 没有。

至于速度:

  • SimpleDom:0.03248 秒。
  • 正则表达式:0.00087 秒。

快 37 倍!

【讨论】:

  • 迄今为止最好的解决方案!使用方便!非常感谢!
  • 您能详细说明一下吗?例如,考虑&lt;li &gt;。 (有多余的空格)
【解决方案4】:

考虑用正则表达式来做这件事是令人生畏的。你考虑过 XSLT 吗?提取 XHTML 文档中所有文本节点(减去脚本和样式内容)的 XPath 表达式将是:

//body//text()[not(ancestor::script)][not(ancestor::style)]

【讨论】:

  • 简单优雅 == 漂亮。
  • 这可能会起作用,除了它还会从
  • 确实如此,请参阅编辑。可能还有其他特殊情况,但这是一般的想法。
  • 在现实世界的 HTML 页面上不起作用,即 HTML 是格式错误的非 XHTML。大多数 XML 解析器不支持“真实世界的 HTML”。这就是为什么我过去使用 HtmlAgilityPack (Google it) 来完成这类任务。
  • 确实,这是一种持续的痛苦。另一种选择是使用 tidy 对页面进行预处理。
【解决方案5】:

使用 perl 语法定义正则表达式,开始可能是:

!<body.*?>(.*)</body>!smi

然后对该组的结果应用以下替换:

!<script.*?</script>!!smi
!<[^>]+/[ \t]*>!!smi
!</?([a-z]+).*?>!!smi
/<!--.*?-->//smi

这当然不会很好地将内容格式化为文本文件,但它会删除所有 HTML(大多数情况下,它可能无法正常工作)。一个更好的主意是使用 XML 解析器以您使用的任何语言正确解析 HTML 并从中提取文本。

【讨论】:

    【解决方案6】:

    简单 HTML 的最简单方法(Python 中的示例):

    text = "<p>This is my> <strong>example</strong>HTML,<br /> containing tags</p>"
    import re
    " ".join([t.strip() for t in re.findall(r"<[^>]+>|[^<]+",text) if not '<' in t])
    

    返回这个:

    'This is my> example HTML, containing tags'
    

    【讨论】:

      【解决方案7】:

      这是一个删除最复杂的 html 标签的函数。

      function strip_html_tags( $text ) 
      {
      
      $text = preg_replace(
          array(
              // Remove invisible content
              '@<head[^>]*?>.*?</head>@siu',
              '@<style[^>]*?>.*?</style>@siu',
              '@<script[^>]*?.*?</script>@siu',
              '@<object[^>]*?.*?</object>@siu',
              '@<embed[^>]*?.*?</embed>@siu',
              '@<applet[^>]*?.*?</applet>@siu',
              '@<noframes[^>]*?.*?</noframes>@siu',
              '@<noscript[^>]*?.*?</noscript>@siu',
              '@<noembed[^>]*?.*?</noembed>@siu',
      
              // Add line breaks before & after blocks
              '@<((br)|(hr))@iu',
              '@</?((address)|(blockquote)|(center)|(del))@iu',
              '@</?((div)|(h[1-9])|(ins)|(isindex)|(p)|(pre))@iu',
              '@</?((dir)|(dl)|(dt)|(dd)|(li)|(menu)|(ol)|(ul))@iu',
              '@</?((table)|(th)|(td)|(caption))@iu',
              '@</?((form)|(button)|(fieldset)|(legend)|(input))@iu',
              '@</?((label)|(select)|(optgroup)|(option)|(textarea))@iu',
              '@</?((frameset)|(frame)|(iframe))@iu',
          ),
          array(
              ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
              "\n\$0", "\n\$0", "\n\$0", "\n\$0", "\n\$0", "\n\$0",
              "\n\$0", "\n\$0",
          ),
          $text );
      
      // Remove all remaining tags and comments and return.
      return strip_tags( $text );
          }
      

      【讨论】:

        【解决方案8】:

        如果您使用的是 PHP,请尝试使用 SourceForge 提供的 Simple HTML DOM。

        否则,谷歌 html2text,你会发现不同语言的各种实现,它们基本上使用一系列正则表达式来吸出所有标记。这里要小心,因为有时会留下没有结尾的标签,以及特殊字符,例如 &(即 &)。

        另外,请注意 cmets 和 Javascript,因为我发现处理正则表达式特别烦人,以及为什么我通常更喜欢让免费的解析器为我完成所有工作。

        【讨论】:

          【解决方案9】:

          我相信你可以做到

          document.body.innerText
          

          这将返回文档中所有文本节点的内容,无论是否可见。

          [edit (olliej): sigh 没关系,这只适用于 Safari 和 IE,而且我也懒得每晚下载一个 firefox 来查看它是否存在于主干中:-/ ]

          【讨论】:

          • 不,在 FF3 中未定义
          • textContent 是标准等效项
          【解决方案10】:

          你不能只使用 C# 提供的 WebBrowser 控件吗?

                  System.Windows.Forms.WebBrowser wc = new System.Windows.Forms.WebBrowser();
                  wc.DocumentText = "<html><body>blah blah<b>foo</b></body></html>";
                  System.Windows.Forms.HtmlDocument h = wc.Document;
                  Console.WriteLine(h.Body.InnerText);
          

          【讨论】:

            【解决方案11】:
            string decode = System.Web.HttpUtility.HtmlDecode(your_htmlfile.html);
                            Regex objRegExp = new Regex("<(.|\n)+?>");
                            string replace = objRegExp.Replace(g, "");
                            replace = replace.Replace(k, string.Empty);
                            replace.Trim("\t\r\n ".ToCharArray());
            
            then take a label and do "label.text=replace;" see on label out put
            

            .

            【讨论】:

            • 而不是 "g" 放入行代码: string replace = objRegExp.Replace(decode, "");
            • 而不是 "g" 放入行代码: string replace = objRegExp.Replace(decode, "");
            猜你喜欢
            • 1970-01-01
            • 2017-10-08
            • 1970-01-01
            • 1970-01-01
            • 2011-12-30
            • 2018-10-11
            • 2023-03-18
            • 2018-05-08
            • 2017-10-31
            相关资源
            最近更新 更多