RegEx匹配XHTML自包含标签以外的打开标签

我需要匹配所有这些开始标签:

<p>
<a href="foo">

但不是这些:

<br />
<hr class="foo" />

我想出了这个,想确保我做对了。我只是捕捉到a-z

<([a-z]+) *[^/]*?>

我相信它说:

  • 找到一个小于,然后
  • 查找(并捕获)az一次或多次,然后
  • 找到零个或多个空格,然后
  • 找到零次或多次贪婪的字符,除了/,然后
  • 寻找大于

我有那个权利吗?更重要的是,您怎么看?

凯泡芙Davaid2020/03/13 20:51:25

尽管为此目的使用正则表达式不适当且无效,但有时正则表达式可以为简单的匹配问题提供快速解决方案,并且在我看来,对于琐碎的工作使用正则表达式并不是那么麻烦。

一篇关于匹配最里面的HTML元素的权威博客文章,这些元素由Steven Levithan撰写。

凯梅2020/03/13 20:51:25

在我看来,您正在尝试匹配结尾不带“ /”的标签。尝试这个:

<([a-zA-Z][a-zA-Z0-9]*)[^>]*(?<!/)>
Green小宇宙伽罗2020/03/13 20:51:25

如果您只是想查找这些标签(没有解析的野心),请尝试以下正则表达式:

/<[^/]*?>/g

我在30秒内编写了它,并在此处进行了测试:http//gskinner.com/RegExr/

它与您提到的标签类型匹配,而忽略了您想忽略的标签类型。

飞云小胖2020/03/13 20:51:25
<\s*(\w+)[^/>]*>

零件说明:

<:起始字符

\s*:标记名称前可能有空格(难看但可行)。

(\w+):标签可以包含字母和数字(h1)。好吧,\w也匹配“ _”,但是我猜并没有伤害。如果好奇,请改用([a-zA-Z0-9] +)。

[^/>]*:除了东西>/直至收盘>

>:关闭 >

无关

对于那些低估正则表达式的人来说,它们仅与正则语言一样强大:

可以将非常规的,甚至不是上下文无关n ba n ba n^(a+)b\1b\1$

反引用FTW

Pro伽罗2020/03/13 20:51:25

关于用于解析(x)HTML的RegExp方法的问题,对于所有谈到某些限制的人的答案是:您没有受过足够的训练来统治这种强大武器的力量,因为NOBODY在这里谈到了递归

一位与RegExp无关的同事通知了我这个讨论,这肯定不是网络上有关这个古老而又热门话题的第一个讨论。

阅读了一些帖子之后,我要做的第一件事是在该线程中寻找“?R”字符串。第二个是搜索“递归”。
不,圣牛,没有找到匹配的东西。
由于没有人提到解析器所基于的主要机制,所以我很快意识到没人明白这一点。

如果(x)HTML解析器需要递归,则没有递归的RegExp解析器不足以实现此目的。这是一个简单的构造。

正则表达式的黑色艺术是难以掌握,所以也许有,我们离开了,而试图和测试我们的个人解决方案捕获整个网络中,一方面进一步的可能性......好吧,我相信它:)

这是魔术图案:

$pattern = "/<([\w]+)([^>]*?)(([\s]*\/>)|(>((([^<]*?|<\!\-\-.*?\-\->)|(?R))*)<\/\\1[\s]*>))/s";

去尝试一下。
它以PHP字符串编写,因此“ s”修饰符使类包含换行符。
这是我在一月份写的PHP手册示例注释参考

(请注意,在该注释中,我错误地使用了“ m”修饰符;尽管未使用^或$定位符,但它已被RegExp引擎丢弃,但应将其删除)。

现在,我们可以从更明智的角度讨论此方法的局限性:

  1. 根据RegExp引擎的具体实现,递归解析的嵌套模式数量可能有所限制,但这取决于所使用的语言
  2. 尽管损坏的(x)HTML不会导致严重错误,但尚未清理

Anyhow it is only a RegExp pattern, but it discloses the possibility to develop of a lot of powerful implementations.
I wrote this pattern to power the recursive descent parser of a template engine I built in my framework, and performances are really great, both in execution times or in memory usage (nothing to do with other template engines which use the same syntax).

达蒙Jim斯丁2020/03/13 20:51:24

正如许多人已经指出的那样,HTML不是一种常规语言,因此很难解析。我的解决方案是使用整洁的程序将其转换为常规语言,然后使用XML解析器使用结果。为此有很多不错的选择。我的程序是使用Java和jtidy编写的,将HTML转换为XML,然后通过Jaxen将xpath转换为结果。

神无Tom2020/03/13 20:51:24

这是一个基于PHP的解析器,它使用一些不合常规的正则表达式来解析HTML。作为该项目的作者,我可以告诉您可以使用正则表达式解析HTML,但是效率不高。如果您需要服务器端解决方案(就像我为wp-Typography WordPress插件所做的那样),则可以使用。

乐Eva2020/03/13 20:51:24

我以前使用过一个名为HTMLParser的开源工具它旨在以各种方式解析HTML,并且很好地达到了目的。它可以将HTML解析为不同的treenode,并且您可以轻松地使用其API从节点中获取属性。检查一下,看看是否可以帮到您。

猴子阳光2020/03/13 20:51:24

如果您需要PHP:

PHP DOM 功能,除非它是格式正确的XML将无法正常工作。无论它们对全人类的使用有多好。

simplehtmldom很好,但是我发现它有点bug,而且它的内存占用很大[将在大页面上崩溃。]

我从未使用过querypath,因此无法评论其有用性。

另一个可以尝试的是我的DOMParser,它对资源非常少,并且我已经很开心地使用了一段时间。简单易学,功能强大。

对于Python和Java,发布了类似的链接。

对于下注者-我仅在XML解析器证明无法承受实际使用时编写类。宗教否决只会阻止发布有用的答案-请使问题保持​​在问题的角度之内。

小胖Gil2020/03/13 20:51:24

您要第一个>不带/这里了解如何做到这一点的详细信息。这被称为否定性回溯。

但是,<bar/></foo>该示例的简单实现最终将在此示例文档中匹配

<foo><bar/></foo>

您能否提供更多有关您要解决的问题的信息?您是否以编程方式遍历标签?

猴子猿2020/03/13 20:51:24

尝试:

<([^\s]+)(\s[^>]*?)?(?<!/)>

它与您的相似,但是最后一个>不能在斜杠之后,并且也可以接受h1

Davaid古一2020/03/13 20:51:24

我不知道您对此有确切的需求,但是如果您还使用.NET,则不能使用HTML Agility Pack吗?

摘抄:

它是一个.NET代码库,可让您解析“网络外” HTML文件。解析器对“真实世界”格式的HTML非常宽容。

Tony阳光2020/03/13 20:51:24

W3C以伪正则表达式形式解释了解析:
W3C Link

遵循了var链接QNameS以及Attribute获得更清晰的画面。
基于此,您可以创建一个很好的正则表达式来处理诸如剥离标签之类的事情。

Itachi村村2020/03/13 20:51:24

中国古代的战略家,一般哲学家孙子说:

据说,如果您认识自己的敌人并认识自己,那么您就可以赢得一百场战斗,而不会遭受任何损失。如果您只了解自己而不是对手,那么您可能会赢或输。如果您既不认识自己,也不认识敌人,那么您将永远危害自己。

在这种情况下,您的敌人是HTML,而您本人或正则表达式。您甚至可能是使用不规则正则表达式的Perl。懂HTML。认识你自己。

我编写了一个描述HTML本质的句。

HTML has
complexity exceeding
regular language.

我还撰写了一个句,描述了Perl中正则表达式的性质。

The regex you seek
is defined within the phrase
<([a-zA-Z]+)(?:[^>]*[^/]*)?>
木心小哥2020/03/13 20:51:24

虽然您无法使用正则表达式解析HTML的答案是正确的,但它们不适用于此处。OP只想用正则表达式解析一个HTML标记,而这可以用正则表达式来完成。

建议的正则表达式是错误的,但是:

<([a-z]+) *[^/]*?>

如果您向正则表达式添加内容,则可以通过回溯将其强制匹配诸如之类的愚蠢内容<a >>[^/]这太宽松了。另请注意,这<space>*[^/]*是多余的,因为[^/]*还可匹配空格。

我的建议是

<([a-z]+)[^>]*(?<!/)>

(?<! ... )(在Perl正则表达式中)负向查找在哪里它显示为“一个<,然后是一个单词,然后是不是>的任何内容,最后一个可能不是/,后跟>”。

请注意,这允许类似<a/ >(与原始正则表达式一样)的东西,因此,如果您想要更严格的限制,则需要构建一个正则表达式以匹配用空格分隔的属性对。

番长神乐小小2020/03/13 20:51:24

在shell中,您可以使用sed解析HTML

  1. 图灵赛德
  2. 编写HTML解析器(作业)
  3. ???
  4. 利润!

相关(为什么不应该使用正则表达式匹配):

米亚十三Harry2020/03/13 20:51:24

我建议使用QueryPath在PHP中解析XML和HTML。它的语法基本上与jQuery相同,只是在服务器端。

Near神奇2020/03/13 20:51:24

我认为这里的缺点是HTML是Chomsky Type 2语法(无上下文语法),而RegEx是Chomsky Type 3语法(常规语法)由于类型2语法从根本上比类型3语法复杂(请参阅Chomsky层次结构),因此从数学上讲无法使用RegEx解析XML。

但是许多人会尝试,有些甚至会声称成功-但直到其他人发现错误并完全把您弄乱为止。

2020/03/13 20:51:24

虽然只有正则表达式的任意 HTML是不可能的,但有时使用它们来解析有限的已知 HTML集合是适当的

如果您想从一小撮HTML页面中抓取数据,然后将它们填充到数据库中,则正则表达式可能会正常工作。例如,我最近想获得我从议会网站上获得的澳大利亚联邦代表的姓名,政党和地区。这是一项有限的一次性工作。

正则表达式对我来说效果很好,并且安装起来非常快。

猿村村2020/03/13 20:51:24

不要听这些家伙。如果将任务分解成小块,则可以使用regex 完全解析上下文无关的语法。您可以使用按顺序执行每个脚本的脚本来生成正确的模式:

  1. 解决停止问题。
  2. 摆一个圆圈。
  3. 计算O(log n)或以下的旅行商问题。如果不止如此,您将用完RAM,引擎将挂起。
  4. 该模式将非常大,因此请确保您有一个无损压缩随机数据的算法。
  5. 几乎在那里-将整个事情除以零。十分简单。

我本人还没有完成最后一部分,但是我知道我已经接近了。CthulhuRlyehWgahnaglFhtagnException由于某种原因,它总是抛出s,因此我将其移植到VB 6并使用On Error Resume Next一旦调查了刚刚在墙上打开的这扇奇怪的门,我将更新代码。

PS Pierre de Fermat也想出了办法,但是他所写的利润不足以编写代码。