了解用于在 html 中的字符串之间查找字符串的正则表达式模式
Understanding regex pattern used to find string between strings in html
我有以下 html 文件:
<!-- <div class="_5ay5"><table class="uiGrid _51mz" cellspacing="0" cellpadding="0"><tbody><tr class="_51mx"><td class="_51m-"><div class="_u3y"><div class="_5asl"><a class="_47hq _5asm" href="/Dev/videos/1610110089242029/" aria-label="Who said it?" ajaxify="/Dev/videos/1610110089242029/" rel="theater">
为了提取 videos/
和 /"
之间的数字串,我使用了以下我发现的方法:
import re
Source_file = open('source.html').read()
result = re.compile('videos/(.*?)/"').search(Source_file)
print result
我已经尝试通过谷歌搜索解释 (.*?)
在此特定实现中的确切工作原理,但我仍然不清楚。有人可以向我解释一下吗?这就是所谓的 "non-greedy" 匹配吗?如果是,那是什么意思?
.
表示任意字符。 *
表示任意次数,包括零次。 ?
确实意味着非贪婪;这意味着它将尝试捕获尽可能少的字符,即,如果正则表达式遇到 /
,它可以将其与 .
匹配,但它宁愿不匹配,因为 .
是非贪婪的,并且由于正则表达式中的下一个字符很乐意匹配 /
,因此 .
不必匹配。如果你没有 ?
,那么 .
会吃掉整个文件的其余部分,因为它会拼命匹配尽可能多的东西,而且因为它匹配所有东西,它会永远持续下去。
可以简单的解释一下:
.
:匹配任何东西(任何字符),
*
:任意次数(至少为零次),
?
:次数越少越好(因此非贪婪)。
videos/(.*?)/"
作为正则表达式匹配(例如)
videos/1610110089242029/"
和第一个捕获组returns 1610110089242029
,因为任何数字都是“任何字符”的一部分,并且其中至少有零个字符。
?
导致这样的事情:
videos/1610110089242029/" something else … "videos/2387423470237509/"
正确匹配 1610110089242029
和 2387423470237509
而不是 1610110089242029/" something else … "videos/2387423470237509
,因此“尽可能少的次数”,因此“非贪婪”。
本文中的?
是重复运算符(+
、*
和?
)的特殊运算符。在可用的引擎中,这会导致重复 lazy 或 non-greedy 或 reluctant 或其他此类条款。通常重复是贪婪的,这意味着它应该尽可能匹配。所以在大多数现代 perl 兼容引擎中你有三种类型的重复:
.* # Match any character zero or more times
.*? # Match any character zero or more times until the next match (reluctant)
.*+ # Match any character zero or more times and don't stop matching! (possessive)
可以在此处找到更多信息:http://www.regular-expressions.info/repeat.html#lazy for reluctant/lazy and here: http://www.regular-expressions.info/possessive.html 所有格(我将在本回答中跳过讨论)。
假设我们有字符串 aaaa
。我们可以用 /(a+)a/
来匹配所有的 a。字面意思是
match one or more a
's followed by an a
.
这将匹配 aaaa
。正则表达式是贪婪的,将匹配尽可能多的 a
。第一个子匹配是 aaa
.
如果我们使用正则表达式 /(a+?)a
这是
reluctantly match one or more a
s followed by an a
or
match one or more a
s until we reach another a
也就是只匹配我们需要的。所以在这种情况下,匹配项是 aa
,第一个子匹配项是 a
。我们只需要匹配一个 a
来满足重复,然后它后面跟着一个 a
.
使用正则表达式在 html 标签、引号和类似内容中进行匹配时经常会出现这种情况——通常保留用于 快速和肮脏的 操作。也就是说,使用正则表达式从非常大且复杂的 html 字符串或带有转义序列的引号字符串中提取可能会导致很多问题,但对于特定用例来说它完全没问题。所以在你的情况下我们有:
/Dev/videos/1610110089242029/
表达式需要匹配 videos/
后跟零个或多个字符后跟 /"
。如果只有一个视频URL那还好,不勉强
但是我们有
/videos/1610110089242029/" ... ajaxify="/Dev/videos/1610110089242029/"
毫不勉强,正则表达式将匹配:
1610110089242029/" ... ajaxify="/Dev/videos/1610110089242029
它会尽量匹配,/
和 "
满足 .
就好了。不情愿地,匹配在第一个 /"
处停止(实际上它回溯了,但您可以单独阅读)。因此你只得到你需要的url部分。
我有以下 html 文件:
<!-- <div class="_5ay5"><table class="uiGrid _51mz" cellspacing="0" cellpadding="0"><tbody><tr class="_51mx"><td class="_51m-"><div class="_u3y"><div class="_5asl"><a class="_47hq _5asm" href="/Dev/videos/1610110089242029/" aria-label="Who said it?" ajaxify="/Dev/videos/1610110089242029/" rel="theater">
为了提取 videos/
和 /"
之间的数字串,我使用了以下我发现的方法:
import re
Source_file = open('source.html').read()
result = re.compile('videos/(.*?)/"').search(Source_file)
print result
我已经尝试通过谷歌搜索解释 (.*?)
在此特定实现中的确切工作原理,但我仍然不清楚。有人可以向我解释一下吗?这就是所谓的 "non-greedy" 匹配吗?如果是,那是什么意思?
.
表示任意字符。 *
表示任意次数,包括零次。 ?
确实意味着非贪婪;这意味着它将尝试捕获尽可能少的字符,即,如果正则表达式遇到 /
,它可以将其与 .
匹配,但它宁愿不匹配,因为 .
是非贪婪的,并且由于正则表达式中的下一个字符很乐意匹配 /
,因此 .
不必匹配。如果你没有 ?
,那么 .
会吃掉整个文件的其余部分,因为它会拼命匹配尽可能多的东西,而且因为它匹配所有东西,它会永远持续下去。
可以简单的解释一下:
.
:匹配任何东西(任何字符),*
:任意次数(至少为零次),?
:次数越少越好(因此非贪婪)。
videos/(.*?)/"
作为正则表达式匹配(例如)
videos/1610110089242029/"
和第一个捕获组returns 1610110089242029
,因为任何数字都是“任何字符”的一部分,并且其中至少有零个字符。
?
导致这样的事情:
videos/1610110089242029/" something else … "videos/2387423470237509/"
正确匹配 1610110089242029
和 2387423470237509
而不是 1610110089242029/" something else … "videos/2387423470237509
,因此“尽可能少的次数”,因此“非贪婪”。
本文中的?
是重复运算符(+
、*
和?
)的特殊运算符。在可用的引擎中,这会导致重复 lazy 或 non-greedy 或 reluctant 或其他此类条款。通常重复是贪婪的,这意味着它应该尽可能匹配。所以在大多数现代 perl 兼容引擎中你有三种类型的重复:
.* # Match any character zero or more times
.*? # Match any character zero or more times until the next match (reluctant)
.*+ # Match any character zero or more times and don't stop matching! (possessive)
可以在此处找到更多信息:http://www.regular-expressions.info/repeat.html#lazy for reluctant/lazy and here: http://www.regular-expressions.info/possessive.html 所有格(我将在本回答中跳过讨论)。
假设我们有字符串 aaaa
。我们可以用 /(a+)a/
来匹配所有的 a。字面意思是
match one or more
a
's followed by ana
.
这将匹配 aaaa
。正则表达式是贪婪的,将匹配尽可能多的 a
。第一个子匹配是 aaa
.
如果我们使用正则表达式 /(a+?)a
这是
reluctantly match one or more
a
s followed by ana
or
match one or morea
s until we reach anothera
也就是只匹配我们需要的。所以在这种情况下,匹配项是 aa
,第一个子匹配项是 a
。我们只需要匹配一个 a
来满足重复,然后它后面跟着一个 a
.
使用正则表达式在 html 标签、引号和类似内容中进行匹配时经常会出现这种情况——通常保留用于 快速和肮脏的 操作。也就是说,使用正则表达式从非常大且复杂的 html 字符串或带有转义序列的引号字符串中提取可能会导致很多问题,但对于特定用例来说它完全没问题。所以在你的情况下我们有:
/Dev/videos/1610110089242029/
表达式需要匹配 videos/
后跟零个或多个字符后跟 /"
。如果只有一个视频URL那还好,不勉强
但是我们有
/videos/1610110089242029/" ... ajaxify="/Dev/videos/1610110089242029/"
毫不勉强,正则表达式将匹配:
1610110089242029/" ... ajaxify="/Dev/videos/1610110089242029
它会尽量匹配,/
和 "
满足 .
就好了。不情愿地,匹配在第一个 /"
处停止(实际上它回溯了,但您可以单独阅读)。因此你只得到你需要的url部分。