fengwhen 发表于 2015-8-29 10:42:22

颠覆想象的php解析获取跨域HTML标签

  本文利用php实现跨域解析获取HTML标签,返回值中将包含1个或多个匹配的标签结果。
  从图中可看出,输入参数包括:URL链接,HTML源码,标签名,标签属性,是否仅匹配第一项。
  1、URL链接
  用于非输入HTML源码情况下获取HTML源码。这个较为通用。
  2、HTML源码
  任意用于测试用的HTML源码都可以。
  3、标签名
  标签名可为任意HTML标签,包括div,ul,table等。
  4、标签属性
  标签属性可用于精确匹配标签,可为:id="main",class="p",name="task",border="0px"等。
  5、是否仅匹配第一项
  只获取第一条返回结果。
  一些效果图如下:

  (图一 URL链接方式)

  (图二直接输入HTML源码方式)

  (图三匹配class属性)

  (图四匹配所有<a>标签)

  (图五只获取第一个匹配项)
  源码展示:


index.html


1 <html>
2 <head>
3   <title>parse DIV</title>
4   <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5   <meta http-equiv="Content-Language" content="zh-CN" />
6   <script type="text/javascript" src="http://files.cnblogs.com/Zjmainstay/jquery-1.6.2.min.js"></script>
7 </head>
8 <body>
9 <span><div>请输入URL链接:</div><input type="text" id="url" value="http://www.baidu.com/">(如:http://www.baidu.com/)</span>
10 <span><div>此次可直接输入页面HTML:</div><input type="text" id="data" value="">(若输入请清空上面URL链接)</span>
11 <span><div>请输入HTML标签名:</div><input type="text" id="tag" value="div">(如div,ul,table,tr,img,input,h1等)</span>
12 <span><div>请输入HTML标签的属性:</div><input type="text" id="tag_id" value='id="u"'>(如id="main",id='main',class="p",name="task"等,可留空匹配无属性标签,区分单双引号)</span>
13 <span><div>只获取第一个匹配项:</div><input type="radio" id="first" now-v="unchecked"></span>
14 <span><input type="button" value="提交" id="parse"></span>
15 <span>解析结果:</span>
16 <textarea id="result" style="float:left;" cols="150" rows="20"></textarea>
17 <script type="text/javascript">
18 $(document).ready(function(){
19   //初始化
20   $("body").css({"background-color":"#ABC"});
21   $("span").css({"float":"left","clear":"both","padding":"3px"});
22   $("div").css({"float":"left","width":"300px"});
23   $("input").attr('size',40);
24   $("#first").attr('checked',null);
25   //单选按钮操作
26   $("#first").unbind().click(function(){
27         if($(this).attr('now-v') == 'unchecked') $(this).attr('checked','checked').attr('now-v','checked');
28         else $(this).attr('checked',null).attr('now-v','unchecked');
29   })
30   //提交处理
31   $("#parse").click(function(){
32         var tag_id,url,tag,data,parentBegin='',parentEnd='';
33         var first = encodeURIComponent($("#first").attr('now-v'));
34         $("input").each(function(){
35             var name = $(this).attr('id');
36             var value = $.trim($(this).val());
37             if(value == '') value='EmPtYValue';
38             value = encodeURIComponent(value);
39             eval(name+'="'+value+'"');
40             if(eval(name) == '') return false;
41         });
42         switch(tag){
43             case 'td':
44               parentBegin = '<table><tr>';
45               parentEnd = '</tr></table>';
46               break;
47             case 'tr':
48               parentBegin = '<table>';
49               parentEnd = '</table>';
50               break;
51             case 'li':
52               parentBegin = '<ul>';
53               parentEnd = '</ul>';
54               break;
55             case 'dt':
56               parentBegin = '<dl>';
57               parentEnd = '</dl>';
58               break;
59             default:
60               parentBegin = '';
61               parentEnd = '';
62               break;
63         }
64
65         $.ajax({
66             url:'parseHtml.php',
67             type:'POST',
68             dataType:'json',
69             async:false,
70             data:{"tag_id":tag_id,"url":url,"tag":tag,"data":data,"first":first},
71             success:function(msg){
72               if(msg != '没有匹配项!') var count = "一共获得"+msg.length+"个匹配。\n";
73               else var count = '';
74               $("#result").html(count+parentBegin+msg.toString().replace(/>,</g,">\n<")+parentEnd);
75               // alert(msg);    //获取第1个匹配
76               // alert($(msg).html());    //获取第2个匹配html内容
77             },
78             error:function(){
79               alert("服务器出错");
80             }
81         });
82   });
83 });
84 </script>
85 </body>
86 </html>

parseHtml.php


1<?php
2   header("Content-type: text/html; charset=utf-8");
3   function getWebTag($tag_id,$url=false,$tag='div',$data=false,$first=false){
4         //默认采用URL获取数据
5         if($url !== false){
6             $data = file_get_contents( $url );
7         }
8         //页面编码判定及转码
9         $charset_pos = stripos($data,'charset');
10         if($charset_pos) {
11             if(stripos($data,'charset=utf-8',$charset_pos)) {
12               $data = iconv('utf-8','utf-8',$data);
13             }else if(stripos($data,'charset=gb2312',$charset_pos)) {
14               $data = iconv('gb2312','utf-8',$data);
15             }else if(stripos($data,'charset=gbk',$charset_pos)) {
16               $data = iconv('gbk','utf-8',$data);
17             }
18         }
19
20         //匹配命中标签至数组$hits
21         preg_match_all('/<'.$tag.'[^<]*?'.$tag_id.'/i',$data,$hits,PREG_OFFSET_CAPTURE);
22         if(count($hits) === 0) {                //未命中,直接返回
23             return '没有匹配项!';
24         }
25
26         preg_match_all('/<'.$tag.'/i',$data,$pre_matches,PREG_OFFSET_CAPTURE);      //获取所有HTML标签前缀
27         preg_match_all('/<\/'.$tag.'/i',$data,$suf_matches,PREG_OFFSET_CAPTURE);   //获取所有HTML标签后缀
28
29         //判断是否<div></div>格式,是则添加结束标签,否则为false;注:img、input等可能不是这种格式,此时$suf_matches为空。
30         if(!empty($suf_matches)) $endTag = '</'.$tag.'>';
31         else $endTag = false;
32         
33         //合并所有HTML标签
34         $htmltags = array();
35         if($endTag !== false){
36             foreach($pre_matches as $index=>$pre_div){
37               $htmltags[(int)$pre_matches[$index]] = 'p';
38               $htmltags[(int)$suf_matches[$index]] = 's';
39             }
40         }else{
41             foreach($pre_matches as $index=>$pre_div){
42               //非<div></div>格式,获取前缀下标后的第一个>作为标签结束
43               $suf_matches[$index] = stripos($data,'>',$pre_matches[$index])+1;
44               
45               $htmltags[(int)$pre_matches[$index]] = 'p';
46               $htmltags[(int)$suf_matches[$index]] = 's';
47             }
48         }
49         //对所有HTML标签按index进行排序
50         $sort = array_keys($htmltags);
51         asort($sort);
52
53         //开始获取命中字符串
54         $hitTagStrings = array();
55         foreach($hits as $hit){
56             $hit = $hit;      //获取命中index
57
58             $count = count($sort);    //循环控制,$count--避免无限循环
59             foreach($pre_matches as $index=>$pre_div){
60               //最后一个$pre_matches[$index+1]会造成数组出界,因此设置其index等于总长度
61               if(!isset($pre_matches[$index+1])) $pre_matches[$index+1] = strlen($data);
62               
63               //<div $hit <div+1    时div被命中
64               if(($pre_matches[$index] <= $hit) && ($hit < $pre_matches[$index+1])){
65                     $deeper = 0;
66                     //弹出被命中HTML标签前的所有HTML标签
67                     while(array_shift($sort) != $pre_matches[$index] && ($count--)) continue;
68                     //对剩余HTML标签进行匹配,若下一个为前缀(p),则向下一层,$deeper加1,
69                     //否则后退一层,$deeper减1,$deeper为0则命中匹配结束标记,计算div长度
70                     foreach($sort as $key){
71                         if($htmltags[$key] == 'p') {    //进入子层
72                           $deeper++;
73                         }else if($deeper == 0) {      //碰到结束标记
74                           $length = $key-$pre_matches[$index];      //长度等于结束标记index 减去 前缀index
75                           break;
76                         }else {                            //碰到子层结束标记
77                           $deeper--;
78                         }
79                     }
80                     $hitTagStrings[] = substr($data,$pre_matches[$index],$length).$endTag;
81                     break;
82               }
83             }
84             //若只获取第一个匹配项,退出循环
85             if($first && count($hitTagStrings) == 1) break;
86         }
87
88         return $hitTagStrings;
89   }
90
91   $tag_id   =   urldecode($_POST['tag_id']);
92   $url      =    urldecode($_POST['url']);
93   $tag      =    isset($_POST['tag'])? urldecode($_POST['tag']) : 'div';
94   $data      =    urldecode($_POST['data']);
95   $first      =    (urldecode($_POST['first']) == 'checked')? true : false;
96   foreach($_POST as $key => $value){
97         if($value == 'EmPtYValue') $$key = false;
98   }
99   echo json_encode(getWebTag($tag_id,$url,$tag,$data,$first));
100
101 //End_php
  
  演示地址:phpParseHtml
  
  注:phpQuery类似jQuery语法实现,非常简便。
  
  
页: [1]
查看完整版本: 颠覆想象的php解析获取跨域HTML标签