• (转)PHP正则表达式匹配嵌套HTML标签的方法和技巧


    正则表达式是一个非常有用的编程技能。一般来说,简单的抓取一个HTML页面的某一条信息,比如<title>标题</title>,是很容易实现的。但是,我们往往要抓取某一个列表页面里的多个重复的<div></div>块里的特定内容,并且<div></div>块还有嵌套的使用,我们抓取的则是每个重复<div></div>块里的多个信息。同时,网页源文件不同于一般的字符串,其还存在大量的回车、换行和制表符,这些都造成了匹配失败。而初学者往往无法判断到底是哪个环节出现了问题,并且看到高度技巧化的正则表达式会感到非常沮丧,从而导致放弃问题的解决。

    经过笔者多日的研究,终于摸索出以下方法和技巧,欢迎大家交流指正。

    请看如下注意点和步骤:

    1.注意/一定要被转义成/,否则会报错

    preg_match_all() [function.preg-match-all]: Unknown modifier

    2.正则表达式用单引号'和/作为开始和结束的标界,比如'/reg partten/',采用这样的写法,正则表达式里的双引号"不必转义

    比如,

    $partten='/<div class="goods_item"><a href="([^<>]+)" target="_blank"><img data-ks-lazyload="([^<>]+)" alt="([^<>]+)" width="" height=""/>/';

    3.需要先去除所有的换行符、制表符、回车等等,对于便于阅读的html源文件由于上述符号的存在会造成无法匹配。

    $str=preg_replace("/[ ]+/","",$str);

    4.我们感兴趣的匹配信息,通常是html元素中的属性的值,因此要去除<>,否则只会匹配最后一条之前的全部信息。

    比如,对于$string="<div><a href=“1.jpg”></a></div><div><a href=“2.jpg”></a></div><div><a href=“3.jpg”></a></div>",

    $partten='/<div><a href=“(.+)”/';的匹配结果是:1.jpg”></a></div><div><a href=“2.jpg”></a></div><div><a href=“3.jpg”></a></div>

    这是因为,上述给出的正则表达式确实没有限定匹配的范围只是第一个超链接<a href=“1.jpg”></a>。

    因此,要想匹配上述三个超链接的 href属性,需要将上述匹配限定在<a href=“1.jpg”>里面,方法也很简单,将(.+)换成([^<>]+),即可。也就是说,这个匹配不包含下一个出现<>的地方,从而将匹配限定在同一个html标签内

    做到以上几点,就可以完全无视html标签嵌套不嵌套的问题,从而抓取到一个页面所有的div重复块中我们感兴趣的内容,下附一例。

     1 <?
     2 //被匹配的html代码
     3 $html='
     4 <div class="goods">
     5     <a href="http://url1111" target="_blank">
     6         <img data-ks-lazyload="http://1111.jpg" alt="alt1111" width="" height=""/>
     7     </a>
     8 </div>
     9 <div class="goods">
    10     <a href="http://url2222" target="_blank">
    11         <img data-ks-lazyload="http://2222.jpg" alt="alt2222" width="" height=""/>
    12     </a>
    13 </div>
    14 <div class="goods">
    15     <a href="http://url3333" target="_blank">
    16         <img data-ks-lazyload="http://3333.jpg" alt="alt3333" width="" height=""/>
    17     </a>
    18 </div>';
    19 
    20 //去掉换行、制表等特殊字符,可以echo一下看看效果
    21 $html=preg_replace("/[	
    
    ]+/","",$html);
    22 
    23 //匹配表达式,注意两点,一是包含在'/ /'里面,再就是/要做转义处理成/
    24 $partern='/<div class="goods"><a href="([^<>]+)" target="_blank"><img data-ks-lazyload="([^<>]+)" alt="([^<>]+)" width="" height=""/></a></div>/';
    25 
    26 //匹配结果
    27 preg_match_all($partern,$html,$result); 
    28 
    29 //打印结果
    30 var_dump($result); 
    31 ?>

      

    输出结果,一共有4个子数组,第一个子数组是匹配到的所有的项,后面三个子数组是我们匹配表达式里的三个匹配项:

     1 array(4) {
     2   [0]=>
     3   array(3) {
     4     [0]=>
     5     string(144) "<div class="goods"><a href="http://url1111" target="_blank"><img data-ks-lazyload="http://1111.jpg" alt="alt1111" width="" height=""/></a></div>"
     6     [1]=>
     7     string(144) "<div class="goods"><a href="http://url2222" target="_blank"><img data-ks-lazyload="http://2222.jpg" alt="alt2222" width="" height=""/></a></div>"
     8     [2]=>
     9     string(144) "<div class="goods"><a href="http://url3333" target="_blank"><img data-ks-lazyload="http://3333.jpg" alt="alt3333" width="" height=""/></a></div>"
    10   }
    11   [1]=>
    12   array(3) {
    13     [0]=>
    14     string(14) "http://url1111"
    15     [1]=>
    16     string(14) "http://url2222"
    17     [2]=>
    18     string(14) "http://url3333"
    19   }
    20   [2]=>
    21   array(3) {
    22     [0]=>
    23     string(15) "http://1111.jpg"
    24     [1]=>
    25     string(15) "http://2222.jpg"
    26     [2]=>
    27     string(15) "http://3333.jpg"
    28   }
    29   [3]=>
    30   array(3) {
    31     [0]=>
    32     string(7) "alt1111"
    33     [1]=>
    34     string(7) "alt2222"
    35     [2]=>
    36     string(7) "alt3333"
    37   }
    38 }

    原文:http://blog.csdn.net/donglynn/article/details/35788879

  • 相关阅读:
    zookeeper 是如何保证事务的顺序一致性的?
    Hibernate的一级缓存和二级缓存有什么区别?
    写出Hibernate中核心接口/类的名称,并描述他们各自的责任?
    请说说你对Struts2的拦截器的理解?
    什么是MVC模式?   
    JDBC中的Statement 和PreparedStatement的区别?
    说说数据库连接池工作原理和实现方案?
    如何删除表中的重复数据,只保留一条记录?
    Where和having都是条件筛选关键字,它们有什么分别?
    JSP和Servlet有哪些相同点和不同点?
  • 原文地址:https://www.cnblogs.com/sallybin/p/4236378.html
Copyright © 2020-2023  润新知