Tips:点此可运行HTML源码

颠覆想象的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="https://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[type=text]").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[0]);    //获取第1个匹配
76                 // alert($(msg[1]).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]) === 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[0]为空。
 30         if(!empty($suf_matches[0])) $endTag = '</'.$tag.'>';
 31         else $endTag = false;
 32         
 33         //合并所有HTML标签
 34         $htmltags = array();
 35         if($endTag !== false){
 36             foreach($pre_matches[0] as $index=>$pre_div){
 37                 $htmltags[(int)$pre_matches[0][$index][1]] = 'p';
 38                 $htmltags[(int)$suf_matches[0][$index][1]] = 's';
 39             }
 40         }else{
 41             foreach($pre_matches[0] as $index=>$pre_div){
 42                 //非<div></div>格式,获取前缀下标后的第一个>作为标签结束
 43                 $suf_matches[0][$index][1] = stripos($data,'>',$pre_matches[0][$index][1])+1;
 44                 
 45                 $htmltags[(int)$pre_matches[0][$index][1]] = 'p';
 46                 $htmltags[(int)$suf_matches[0][$index][1]] = 's';
 47             }
 48         }
 49         //对所有HTML标签按index进行排序
 50         $sort = array_keys($htmltags);
 51         asort($sort);
 52 
 53         //开始获取命中字符串
 54         $hitTagStrings = array();
 55         foreach($hits[0] as $hit){
 56             $hit = $hit[1];        //获取命中index
 57 
 58             $count = count($sort);    //循环控制,$count--避免无限循环
 59             foreach($pre_matches[0] as $index=>$pre_div){
 60                 //最后一个$pre_matches[0][$index+1]会造成数组出界,因此设置其index等于总长度
 61                 if(!isset($pre_matches[0][$index+1][1])) $pre_matches[0][$index+1][1] = strlen($data);
 62                 
 63                 //<div $hit <div+1    时div被命中
 64                 if(($pre_matches[0][$index][1] <= $hit) && ($hit < $pre_matches[0][$index+1][1])){
 65                     $deeper = 0;
 66                     //弹出被命中HTML标签前的所有HTML标签
 67                     while(array_shift($sort) != $pre_matches[0][$index][1] && ($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[0][$index][1];        //长度等于结束标记index 减去 前缀index
 75                             break;
 76                         }else {                            //碰到子层结束标记
 77                             $deeper--;
 78                         }
 79                     }
 80                     $hitTagStrings[] = substr($data,$pre_matches[0][$index][1],$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

 

 

注:phpQuery类似jQuery语法实现,非常简便。

 

 

posted @ 2012-09-21 11:00  Zjmainstay  阅读(2917)  评论(4编辑  收藏  举报