使用PHP正则匹配图片地址

最近在 WordPress 某项目中需要从文章内容中匹配多个图片,在实践的过程中掉进坑里爬了很久才出来。最开始我使用的正则表达式如下:

  1. <img.*?src=[\'|\"](.*?(?:[\.gif|\.jpg|\.png|\.jpeg]))[\'|\"].*?[\/]?>

然而使用这个正则表达式来匹配图片的话就会有一个缺陷,如果 src 里面的值不是一个标准的图片地址,那么很有可能就会匹配出错。比如下面的代码,内容中共有三个 img 标签,其中第二个 img 的 src 属性是 http://image-demo.oss-cn-hangzhou.aliyuncs.com/example.jpg?x-oss-process=image/resize,m_fixed,h_100,w_100

<?php
$content = '<p>我是第一段</p><p>我是第二段图片前文字<img src="http://image-demo.oss-cn-hangzhou.aliyuncs.com/example.jpg" />我是第三段图片前文字<img src="http://image-demo.oss-cn-hangzhou.aliyuncs.com/example.jpg?x-oss-process=image/resize,m_fixed,h_100,w_100" /><img src="http://image-demo.oss-cn-hangzhou.aliyuncs.com/example.jpg" /></p><p>我是第四段文字</p>';
$image_pattern = "/<img.*?src=[\'|\"](.*?(?:[\.gif|\.jpg|\.png|\.jpeg]))[\'|\"].*?[\/]?>/";
preg_match_all( $image_pattern, $content, $matches );
var_dump( $matches );

执行结果如下,可以看到因为第二个 img 标签里面的 src 并不是一个预想的那样,导致匹配第二个 img 的时候直接把第三个 img 一起包含进来了。当然我这里只是举了一个阿里云 oss 图片处理地址,真实的情况里面可能还有更偏离预想的,比如可能干脆是一个错误的地址。

array(2) {
  [0]=>
  array(2) {  
  [0]=>  
  string(72) "<img src="http://image-demo.oss-cn-hangzhou.aliyuncs.com/example.jpg" />"    [1]=>    string(191) "<img src="http://image-demo.oss-cn-hangzhou.aliyuncs.com/example.jpg?x-oss-process=image/resize,m_fixed,h_100,w_100" /><img src="http://image-demo.oss-cn-hangzhou.aliyuncs.com/example.jpg" />" 
 } 
 [1]=>  
array(2) {  
  [0]=> 
   string(58) "http://image-demo.oss-cn-hangzhou.aliyuncs.com/example.jpg"   
 [1]=> 
   string(177) "http://image-demo.oss-cn-hangzhou.aliyuncs.com/example.jpg?x-oss-process=image/resize,m_fixed,h_100,w_100" /><img src="http://image-demo.oss-cn-hangzhou.aliyuncs.com/example.jpg"  
}
}

正确匹配方法

指导思想:我们匹配的时候,不要限定图片路径格式,也就是不管图片的 src 属性值是合规还是不合规,先匹配出来,再处理。所以使用下面的正则表达式即可。

  1. <img.*?src=[\'|\"](.*?)[\'|\"].*?[\/]?>

先把 img 标签里面的 src 值匹配出来,判断这个值是否合规,参考代码如下:

  1. <?php
  2. $content = '<p>我是第一段</p><p>我是第二段图片前文字<img src="http://image-demo.oss-cn-hangzhou.aliyuncs.com/example.jpg" />我是第三段图片前文字<img src="http://image-demo.oss-cn-hangzhou.aliyuncs.com/example.jpg?x-oss-process=image/resize,m_fixed,h_100,w_100" /><img src="http://image-demo.oss-cn-hangzhou.aliyuncs.com/example.jpg" /></p><p>我是第四段文字</p>';
  3.  
  4. $image_pattern = "/<img.*?src=[\'|\"](.*?)[\'|\"].*?[\/]?>/";
  5. preg_match_all( $image_pattern, $content, $matches );
  6.  
  7. if( !empty( $matches[1]) ){
  8. 	//循环匹配到的src
  9. 	foreach ($matches[1] as $src) {
  10. 		$src_real = strtok($src,'?'); //分割,去掉请求参数
  11. 		$ext = pathinfo( $src_real, PATHINFO_EXTENSION ); //获取拓展名
  12. 		if( in_array( $ext, ['jpg','jpeg','gif','png'] ) ){
  13. 			echo $src_real.PHP_EOL;
  14. 		}
  15. 	}
  16. }

输出结果符合要求,如下:

  1. http://image-demo.oss-cn-hangzhou.aliyuncs.com/example.jpg
  2. http://image-demo.oss-cn-hangzhou.aliyuncs.com/example.jpg
  3. http://image-demo.oss-cn-hangzhou.aliyuncs.com/example.jpg

 

平时不经常用到,用起来的时候总会去重复写正则。

于是准备了下面两个正则,能匹配带HTTP和不带HTTP的链接。
[php]
preg_match_all("/<img[^>]+src=[\"|'| |\s]+?([^>]*?\.(gif|jpg|png|bmp|jpeg))/isU", $content, $img_array);
$img_array = array_unique($img_array[2]);
[/php]

[php]
preg_match_all("/(src)=[\"|'| ]{0,}(http:\/\/([^>]*)\.(gif|jpg|png))/isU", $content, $img_array);
$img_array = array_unique($img_array[2]);
[/php]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值