我正在使用一个应用程序搜索这个网站,我现在无权控制,并且想知道是否有办法忽略仅使用正则表达式的重复匹配。
现在我写这个是为了获取页面源代码
中图像源的匹配使用它来检索srcs
<span> <img id="imgProduct.*? src="/(.*?)" alt="
来自这个
<span> <img id="imgProduct_1" class="SmPrdImg selected"
onclick="(some javascript);" src="the_src_I_want1.jpg" alt="woohee"> </span>
<span> <img id="imgProduct_2" class="SmPrdImg selected"
onclick="(some javascript);" src="the_src_I_want2.jpg" alt="woohee"> </span>
<span> <img id="imgProduct_3" class="SmPrdImg selected"
onclick="(some javascript);" src="the_src_I_want3.jpg" alt="woohee"> </span>
唯一的问题是,上面列出的完全相同的代码在源代码中的重复方式较低。有没有办法只使用正则表达式忽略或删除重复项?
答案 0 :(得分:2)
你的模式不是很好;它对于您目前存在的确切源代码来说太具体了。正如@Truth评论的那样,如果改变了,你就会打破你的模式。我建议更像这样的东西:
<img[^>]*src=['"]([^'"]*)['"]
无论您的源代码有多少变化,这都会与任何src
标记内的任何<img>
属性的内容相匹配。
为了防止使用正则表达式重复,您需要前瞻,这可能非常慢。我使用正则表达式不推荐。这只是为了表明你可以,如果你不得不这样做。您需要的模式是这样的(我使用Notepad ++的正则表达式搜索进行了测试,它基于PCRE并且比JavaScript更强大,但我有理由相信JavaScript的正则表达式解析器可以处理这个问题。)
<img[^>]*src=['"]([^'"]*)['"](?!(?:.|\s)*<img[^>]*src=['"]\1['"])
然后,您将获得每个src
的最后一个实例的匹配。
为了说明,这里是模式的工作原理:
<img[^>]*src=['"]([^'"]*)['"]
这确保我们在<img>
出现时位于src
标记内,然后确保我们只匹配引号内的内容(可以是单引号或双引号;因为它们都不是是文件名中的合法字符我们不必担心混合报价类型或转义引号。
(?!
(?:
.
|
\s
)*
<img[^>]*src=['"]\1['"]
)
(?!
开始出现负面预测:我们要求在此之后无法匹配以下模式。
然后(?:.|\s)*
匹配任何字符或任何空格。这是因为JavaScript的.
与换行符不匹配,而\s
会匹配换行符。大多数情况下,我很懒,并且不想为任何可能的行结尾写出模式,所以我只使用了\s
。当然,*
意味着我们可以拥有任意数量的这些。这意味着在文件的其余部分中无法找到 where 以下(仍然是否定前瞻的一部分)。 (?:
代替(
意味着不会记住此括号内的反向引用。
该位是<img[^>]*src=['"]\1['"]
。这与初始模式非常相似,但我们不是使用src
捕获([^'"]*)
,而是使用src
引用之前捕获的\1
。
因此,该模式说“匹配src
中任何img
的任何img
,其中src
中没有任何src
与文件其余部分中的任何位置相同img
,”这意味着您只获取每个src
的最后一个实例,并且没有重复项。
如果你想删除{{1}}出现不止一次的{{1}}的所有个实例,顺便提一下,我认为你运气不好。 JavaScript不支持lookbehind,并且绝大多数正则表达式引擎都不会允许这样复杂的lookbehind 无论如何。
答案 1 :(得分:1)
我不会太努力使它们变得独一无二,只需在与array_unique的preg匹配之后在PHP中执行此操作:
$pattern = '~<span> <img id="imgProduct.*? src="/(.*?)" alt="~is';
$match = preg_match_all($pattern, $html, $matches);
if ($match)
{
$matches = array_unique($matches[1]);
}
如果您使用的是JavaScript,那么您需要使用另一个函数而不是array_unique,请检查PHPJS: http://phpjs.org/functions/array_unique:346