【发布时间】:2011-04-26 11:23:01
【问题描述】:
我正在创建一个应用程序,它将以 URL 作为输入,从网络上检索页面的 html 内容并提取 标签中不包含的所有内容。换句话说,该页面的访问者所看到的页面的文本内容。这包括“屏蔽”封装在 <script></script>、<style></style> 和 <!-- --> 中的所有内容,因为这些部分包含未封装在标签中的文本(但最好单独保留)。
我已经构建了这个正则表达式:
(?:<(?P<tag>script|style)[\s\S]*?</(?P=tag)>)|(?:<!--[\s\S]*?-->)|(?:<[\s\S]*?>)
它正确地选择了我想忽略的所有内容,并且只留下页面的文本内容。但是,这意味着我要提取的内容不会出现在匹配集合中(我在 Visual Studio 2010 中使用 VB.Net)。
有没有办法像这样“反转”整个文档的匹配,这样我就可以匹配上面正则表达式中匹配遗漏的所有文本字符串?
到目前为止,我所做的是在最后添加另一个替代方案,即选择“任何不包含 的序列”,这意味着剩余的文本。我在捕获组中命名了最后一位,当我遍历匹配项时,我检查“文本”组中是否存在文本。这行得通,但我想知道是否可以通过正则表达式完成所有操作,并且 just 最终会在纯文本上匹配。
这应该是通用的,不知道 html 中的任何特定标签。它应该提取 all 文本。此外,我需要保留原始 html,以便页面保留其所有链接和脚本 - 我只需要能够提取文本,以便我可以在其中执行搜索和替换,而不必担心“重命名”任何标签、属性或脚本变量等(所以我不能只对我得到的所有匹配项进行“替换”,因为即使我得到了我需要的东西,将其重新插入到正确的位置也是一件麻烦事功能齐全的文档)。
我想知道这是否可以使用正则表达式(我知道 HTML Agility Pack 和 XPath,但不喜欢)。
有什么建议吗?
更新: 这是我最终得到的(基于正则表达式的)解决方案:http://www.martinwardener.com/regex/,在一个演示 Web 应用程序中实现,该应用程序将显示活动的正则表达式字符串以及一个允许您在任何在线 html 页面上运行解析的测试引擎,给出您解析时间并提取结果(分别针对链接、url 和文本部分 - 以及在完整 HTML 文档中突出显示所有正则表达式匹配的视图)。
【问题讨论】:
-
你可以用
`字符包围短代码块。 -
正则表达式在选择正确的部分方面做得很好——可能比使用任何 DOM 等方法(或..?)更优雅。所以除了“反转”部分,我对使用正则表达式非常满意——它非常紧凑,代码明智。我有两种候选方法来完成这项工作:向正则表达式 (
|(?P<text>[^<>]*)) 添加一个额外的部分,它实际上将选择剩余文本作为隔离匹配 - 由于该捕获组有一个名称,因此可以在随后的迭代。这行得通,只是我注意到它也只找到了一些令我困惑的其他“匹配项”。 -
另一种可能性(我还没有仔细考虑过,但它应该可以工作,虽然这是我想避免的繁琐)是在上面的主要帖子中使用正则表达式,省略了文本零件 - 并“手动”跟踪比赛。因为他们都让我知道匹配在页面中的哪个位置开始,以及匹配字符串的长度,所以我会使用一个匹配的索引+长度和下一个匹配的索引之间的差异来确定然后代表什么文档的纯文本部分,不包含在任何“掩码”中。
-
这样我就可以在与匹配迭代相同的操作中进行单词搜索/替换,并且生成的文档将准备就绪,包括所有正确的 html 和脚本代码。
-
更新:我不再困惑了。事实证明,没有将 RegexBuddy 语法正确转换为 .Net 正则表达式语法是我的错(它们在命名捕获组的方式上有所不同,我在更改它们时忽略了一个)。因此,该例程完美运行。我可以在 10 行代码中完成。
标签: html regex text extract invert