正则表达式,用于从 HTML 中提取文本



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

我想删除

  • 任何 HTML 标记
  • 任何脚本
  • 任何 CSS 样式

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

删除 javascript 和 CSS:

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

移除标签

<.*?>

你不能真正用正则表达式解析 HTML。 太复杂了。 RE 根本无法正确处理<![CDATA[部分。 此外,某些常见的HTML内容(如&lt;text>)可以在浏览器中作为正确的文本工作,但可能会使天真的RE感到困惑。

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


此外,根据设计,浏览器可以容忍格式错误的 HTML。 因此,您经常会发现自己试图解析显然不恰当的 HTML,但碰巧在浏览器中工作正常。

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

需要一个正则表达式解决方案(在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没有。

至于速度:

  • 简单多姆:0.03248秒
  • 正则表达式:0.00087秒

快 37 倍!

考虑使用正则表达式执行此操作是令人生畏的。您是否考虑过 XSLT?提取XHTML文档中的所有文本节点(减去脚本和样式内容)的XPath表达式将是:

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

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

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

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

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

这当然不会很好地格式化为文本文件,但它会删除所有 HTML(大多数情况下,在某些情况下它可能不太正确)。不过,更好的主意是使用您正在使用的任何语言的XML解析器来正确解析HTML并从中提取文本。

简单

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'

这是一个删除最复杂的 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 );
    }

如果您使用的是PHP,请尝试在SourceForge上找到的Simple HTML DOM。

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

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

我相信你可以做到

document.body.innerText

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

[编辑(Olliej):,没关系,这仅适用于Safari和IE,我懒得每晚下载Firefox以查看它是否存在于后备箱中:-/]

你不能只使用 C# 提供的 Web 浏览器控件吗?

        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);
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("trn ".ToCharArray());
then take a label and do "label.text=replace;" see on label out put

.

相关内容

  • 没有找到相关文章

最新更新