颠覆想象的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]