如何使用PHP服务端代理抓取网页内容

最近公司暂时断开外网,只开放公司自己所有的站点允许访问,说实在的,做WEB开发的断网,真是让人哭笑不得......

由于需要查找资料,只好简单写了一个PHP的服务端代理页面来用一下!

简单框架页面

<style type="text/css">
*{margin:0;padding:0;}
html,body{overflow:hidden;}
td{padding:0;vertical-align:top;}
</style>
<table width="100%" height="100%" cellspacing="0" cellpadding="0" border="0">
<tr>
<td style="width:100%;height:25px;background:#d4d0c8;padding:5px 10px;">
<form method="post" action="action_get.php" target="actioncontent" style="margin:0;padding:0;">
<input type="text" id="targeturl" name="targeturl" style="width:100%;border:1px inset;margin:0;" />
</form>
</td>
<td style="width:180px;height:25px;background:#d4d0c8;padding:5px 10px 5px 0;">
<select style="width:180px;"><option value="">Quick Links</option><option value="http://www.google.com">http://www.google.com</option><option value="http://www.baidu.com">http://www.baidu.com</option><option value="http://www.bing.com">http://www.bing.com</option></select>
</td>
</tr>
<tr>
<td colspan="2">
<iframe name="actioncontent" style="width:100%;height:100%;"></iframe>
</td>
</tr>
</table>
<script type="text/javascript">
window.onload = function(){
    document.getElementById('targeturl').focus();
};
var dform = document.getElementsByTagName('form')[0];
var dselect = document.getElementsByTagName('select')[0];
var dipt = document.getElementById('targeturl');
dselect.onchange = function(){
    if(this.value!=''){
        dipt.value = this.value;
        dform.submit();
    }
};
dform.onsubmit = function(){
    var dv = document.getElementById('targeturl');
    var sv = dv.value.replace(/\s/g,'');
    dv.value = sv;
    return true;
};
</script>

PHP代理页面

<?php
//使用Snoopy的抓页功能
include "Snoopy.class.php";
//目标URL
$url = $_REQUEST['targeturl'];
//下载类文件列表
$download = array(
    'pdf'=>'application/pdf',
    'rar'=>'application/octet-stream',
    'chm'=>'application/octet-stream',
    'ppt'=>'application/vnd.ms-powerpoint',
    'doc'=>'application/msword',
    'xls'=>'application/vnd.ms-excel',
    'exe'=>'application/octet-stream',
    'gif'=>'image/gif',
    'jpg'=>'image/jpeg',
    'jpeg'=>'image/jpeg',
    'png'=>'image/png'
);
//取文件扩展名
function getextend($file_name){
 $extend = pathinfo($file_name);
 $extend = strtolower($extend["extension"]);
 return $extend;
}
//将所有传递过来的参数列出来
$par = array();
$GetPost = array_merge($_POST,$_GET);
foreach($GetPost As $Key=>$Value){
 if($Key!='targeturl'){
  $Value = str_replace("%25","%",$Value);
  array_push($par,($Key . "=" . $Value));
 }
}
//判断目标URL是否带有?(即是否带有参数)
$cc = strpos($url,"?") ? "&" : "?";
//重组URL
$geturl = !$par ? $url : $url.$cc.implode("&",$par);
//抓取重组后的URL页面内容
$snoopy = new Snoopy;
$snoopy->fetch($geturl);
//检测当前文件是否为下载类型
$sftype = getextend($url);
$bdown = @$download[$sftype];
//如果是,则下载该文件
if($bdown){
 $query = $snoopy->results;
 header("Content-type: ".$bdown);
 header("Content-Disposition:inline;filename=".$url);
 header('Cache-Control:must-revalidate,post-check=0,pre-check=0');
 header('Expires:0');
 header('Pragma:public');
 echo $query;
 exit;
}
//替换目标内容中脚本里有可能替换父窗口地址的代码
$org = str_replace("top.location","top.title",$snoopy->results);
//尝试转换目标内容编码到UTF-8
$opt = iconv("gbk","utf-8",$org);
//判断目标内容编码为GBK或UTF-8
$ec = strlen($opt)?"gbk":"utf-8";

?>
<script type="text/javascript">
//封闭运行,避免与后面内容中脚本混乱
(function(){
/*如果是js,css,txt类型文件,则直接输出,不做处理*/
var sftype = '<?php echo $sftype;?>';
if(/(?:js|css|txt)/i.test(sftype)){return;}
var createIPH = function(name,value){if(!name){return;}if(/msie/i.test(navigator.appVersion)){return document.createElement('<input type="hidden" name="'+name+'" value="'+value+'"/>');}else{var dfi = document.createElement('input');dfi.type = 'hidden';dfi.name = name;dfi.value = value;return dfi;}};
//回显目标URL到父窗口文本框
var dtu = top.document.getElementById('targeturl');
if(dtu){dtu.value = '<?php echo $geturl;?>';}
//目标URL及domain
var sref = '<?php echo $url;?>';
var sdomain = (/^(http:\/\/[^\/]*)/i.test(sref))?RegExp.$1:'';
//插入外部样式
var newStyleSheet = function(shref){
    var ds = document.createElement('link');
    ds.rel = 'styleSheet';
    ds.type='text/css';
    ds.href = shref;
    document.getElementsByTagName('head')[0].appendChild(ds);
};
//页面加载后执行下面的过程
var process = function(){
//抓取页面中外部样式链接
var dstyle = document.getElementsByTagName('link'),ls = dstyle.length;
//抓取页面中所有链接
var dlink = document.getElementsByTagName('a'),la = dlink.length;
//抓取页面中所有表单
var dform = document.getElementsByTagName('form'),lf = dform.length;
//抓取页面中所有图片
var dimg = document.getElementsByTagName('img'),lm = dimg.length;
//遍历所有外部样式链接,重新插入替换后的样式文件
for(var i=0;i<ls;i++){
        var shref = dstyle[i].href;
        if(!shref){continue;}
        shref = shref.toString().replace(/^http:\/\/www\.w3cgroup\.com(?:\/geturl)?/i,sdomain);
        var newhref = (/^http/i.test(shref))?'http://www.w3cgroup.com/geturl/action_get.php?targeturl='+shref:'http://www.w3cgroup.com/geturl/action_get.php?targeturl='+sdomain+'/'+shref.replace(/^\/*/,'');
        newStyleSheet(newhref);
}
 //遍历所有链接,替换它们的href地址
 for(i=0;i<la;i++){
 var src = dlink[i].href.toString().replace(/^http:\/\/www\.w3cgroup\.com(?:\/geturl)?/i,sdomain);
 var oargs = getArgs(src),ahref = [];
 //UTF-8编码参数值
 for(var d in oargs){
  if(!d||d=='filename'||!oargs[d]){continue;}
  ahref.push(d+'='+encodeURIComponent(encodeURI(oargs[d])));
 }
 var ghref = ahref.length?oargs.filename+'?'+ahref.join('&'):oargs.filename;
 //重设链接地址
 dlink[i].href = 'http://www.w3cgroup.com/geturl/action_get.php?targeturl='+ghref;
 }
 //遍历所有表单,替换它们的action地址
 for(i=0;i<lf;i++){
 //抓取表单action并处理
 var src = dform[i].action.toString().replace(/^http:\/\/www\.w3cgroup\.com(?:\/geturl)?/i,sdomain);
 if(!(/^http/.test(src))){src = (/^\/.*$/.test(src))?(sdomain+src):(sdomain+'/'+src);}
 //创建一个隐藏域targeturl,值为上面处理的src地址
 var dfi = createIPH('targeturl',src);
 dform[i].appendChild(dfi);
 //创建一个隐藏域ie,值为utf-8,纯属为搜索引擎使用
 var dfi2 = createIPH('ie','utf-8');
 dform[i].appendChild(dfi2);
 //重设表单提交目标窗口
 dform[i].target = 'actioncontent';
 //重设表单action地址
 dform[i].action = 'http://www.w3cgroup.com/geturl/action_get.php';
 //重设表单onsubmit事件,用来UTF8编码字段值
 dform[i].onsubmit = function(){
  var dlms = this.elements,l = dlms.length-1,pn = '',pt = '',pv = '';
  for(var i=0;i<l;i++){
   pn = dlms[i].name,pt = dlms[i].type,pv = dlms[i].value;
   if(!pn||pn=='targeturl'||pn=='ie'){continue;}
   if(pt=='submit'||pt=='reset'||pt=='button'){
    dlms[i].value = encodeURIComponent(pv);
   }else{
    dlms[i].value = encodeURIComponent(encodeURI(pv));
   }
  }
 };
 }
//遍历所有图片,重新载入
for(i=0;i<lm;i++){
        var src = dimg[i].src;
        if(!src){continue;}
        src = src.toString().replace(/^http:\/\/www\.w3cgroup\.com(?:\/geturl)?/i,sdomain);
        var newsrc = (/^http/i.test(src))?'http://www.w3cgroup.com/geturl/action_get.php?targeturl='+src:'http://www.w3cgroup.com/geturl/action_get.php?targeturl='+sdomain+'/'+src.replace(/^\/*/,'');
        dimg[i].src = newsrc;
}
};
//绑定该过程到window.onload
if(document.attachEvent){window.attachEvent('onload',process);}else{window.addEventListener('load',process,false);}
})();
</script>
//脚本放在输出内容前,避免内容中可能出现脚本错误而导致我们要做的事情被废掉
//输出抓到的目标页面内容
<?php echo $scontent;?>

在这个小作品中,我编写了一个重要的JavaScript函数easyUTF8,它可以很方便地在JavaScript脚本中将GBK编码的内容转换为UTF-8编码

我们还处理了一下表单中添加项目的兼容问题,注意看createIPH函数,在IE中创建的表单项内容,在指定name和value时可能会出现我们不希望的结果,这在DHTML手册中已经有过描述了。



[本日志由 dh20156 于 2009-12-23 07:41 PM 编辑]
文章来自: DHTML精英,WEB前端专家!
引用通告: 查看所有引用 | 我要引用此文章
Tags: php 代理
评论: 2 | 引用: 0 | 查看次数: 1823
回复回复poplong[2009-12-18 03:54 PM | del]
怎么不能用啊?能发一份给我吗?QQ邮箱519901【AT】qq.com
引用来自 dh20156 dh20156 于 2009-12-19 09:25 AM 回复
请先下载snoopy.class.php,然后上文中出现的http://www.w3cgroup.com字样改成你自己的网址。
回复回复小胡子[2009-12-16 02:08 PM | del]
不知道博主能否提供下载 供研究下,Email: 178372561@qq.com
引用来自 dh20156 dh20156 于 2009-12-17 10:39 PM 回复
所有文件都贴出来了啊,你还要什么下载?Snoopy.class.php到网上down一个就好了 ^_^
发表评论
昵 称:
密 码: 游客发言不需要密码.
内 容:
验证码: 验证码
选 项:
虽然发表评论不用注册,但是为了保护您的发言权,建议您注册帐号.
字数限制 1000 字 | UBB代码 关闭 | [img]标签 关闭