使用 php 删除重复的 img 标签


Removing duplicated img tags using php

在这样的字符串中:

<body>
   <img src="specialpic" />
   <p>sometext</p><br>
   <img src="/somepic.png" />
   <img src="/somepic.png" />
   <p>someotherstuff</p>
   <img src="/anotherpic.png" />
   <img src="/anotherpic.png" />
</body>

如何删除每个重复的img标签,以便最终字符串如下所示?

<body>
   <img src="specialpic" />
   <p>sometext</p><br>
   <img src="/somepic.png" />
   <p>someotherstuff</p>
   <img src="/anotherpic.png" />
</body>
为此

使用HTML解析器。请参阅此示例与 DOMDocument

初始化DOMDocument并加载您的 HTML 文件:

$dom = new DOMDocument();
libxml_use_internal_errors(1);
$dom->formatOutput = True;
$dom->loadHTML($html);

初始化两个空数组:$img将包含唯一的src值,$toDelete将包含要删除的重复节点:

$img = $toDelete = array();

搜索带有<img>标签的所有节点:

$nodes = $dom->getElementsByTagName( 'img' );

对于每个找到的节点,将src属性与数组进行比较$img:如果找到,则将当前节点添加到$toDelete,否则src值添加到$img

foreach( $nodes as $node )
{
    $src = $node->getAttribute('src' );
    if( in_array( $src, $img ) ) $toDelete[] = $node;
    else                         $img[] = $src;
}

最后,执行foreach循环以删除找到的节点:

foreach( $toDelete as $node ) $node->parentNode->removeChild( $node );

要打印生成的 HTML,请执行以下操作:

echo $dom->saveHTML();

请注意$toDelete数组的用法。理论上我们可以直接删除第一个foreach内的节点,但通过这种方式我们减少了原始搜索结果的 len,因此跳过了下一个节点。


  • 阅读更多 关于 DOMDocument
  • 阅读为什么你不能用正则表达式解析 [X]HTML

虽然由于HTML的性质不完全推荐,但根据您的问题,并且假设图像标签始终采用相同的格式,或者在比较时完全相同的字符,这可以通过子模式实现。

试试这个:

$input =<<<EOF
<body>
<img src="specialpic" />
<p>sometext</p><br>
<img src="/somepic.png" />
<img src="/somepic.png" />
<p>someotherstuff</p>
<img src="/anotherpic.png" />
<img src="/anotherpic.png" />
</body>
EOF;
$result = preg_replace('|(<img's*src=.*?'s*/>'s*)'1*|s', ''1', $input);

结果应该是您所希望的确切输出。在这里查看: https://3v4l.org/sbgDX

  • 's*是匹配任何空格
  • .*?是对介于两者之间的任何字符的非贪婪匹配
  • 模式参数中的'1*表示子模式重复 0 或更多,在换行符后或匹配模式后的任何空格

这篇文章的灵感。