转发一个PHP抓取网页快照程序

转发一个PHP抓取网页快照程序,代码是转发的,注释是原创的,帮助新人理解。

snap.class.php

<?PHP
//====================================================
// FileName: snap.class.php
// Summary: 网页快照
// Author: millken(迷路林肯)
// LastModifed:2007-06-29
// copyright (c)2007 [email]millken@gmail.com[/email]
//====================================================
class snap{
        var $dir;
        var $log;
        var $contents; // 缓冲文件内容
        var $filename; // 缓冲文件的文件地址
        var $host; // 目标地址
        var $name; // 缓冲文件的文件名, 值是Url的MD5码
        var $data_ts; // 缓冲文件的时间戳
        var $ttl; // 超时时间
        var $url; // 需要抓快照的Url地址
        var $ts; //
        function snap(){
            $this->log = "New snap() object instantiated.<br />\n";        
            $this->dir = dirname(__FILE__)."/";
        }
        /*
            获取网页快照。
            参数:
                url:网页地址
                ttl:超时时间,单位为秒。
                    超过这个时间后从网页上获取,在此时间内直接读缓冲文件。
            返回值:
                无
        */
        function fetch($url="",$ttl=10) {
            $this->log .= "--------------------------------<br />fetch() called<br />\n";
            $this->log .= "url: ".$url."<br />\n";
            // 验证Url是否合法。
            $hosts = parse_url($url);
            $this->host = $hosts['scheme'].'://'.$hosts['host'].'/';
            if (!$url) {
                $this->log .= "OOPS: You need to pass a URL!<br />";
                return false;
            }
            $this->ttl = $ttl;
            $this->url = $url;
            $this->name = md5($this->url);
            $this->filename = $this->dir.$this->name;
            $this->log .= "Filename: ".$this->filename."<br />";
            $this->getFile_ts();
            $this->file_get_content();
        }
        /*
            获取快照内容。
            如果超时,则从网页上直接获取,否则从缓存文件获取
            参数:
                无
            返回值:
                true:成功, false:失败
        */
        function file_get_content(){
        // 打开缓冲区
            ob_start();
            $this->ts = time() - $this->data_ts;
            // 如果超时,则从网页上取得快照,否则,直接从缓冲区内取得
            if($this->data_ts <> 0 && $this->ts <= $this->ttl){
                $this->log .= "cache has expired<br />";
                @readfile($this->filename);        
                $this->contents = ob_get_contents();
                ob_end_clean();
            }else{
                $this->log .= "cache hasn't expired<br />";                
                @readfile($this->url);        
                $this->contents = ob_get_contents();
                ob_end_clean();
                $this->saveToCache();
            }
            return true;
        }
        /*
            保存快照到缓存文件。
            参数:
                无
            返回值:
                true:成功, false:失败
        */
        function saveToCache(){
            $this->log .= "saveToCache() called<br />";
            //建立一个新文件用户缓存网页快照
            if (!$fp=@fopen($this->filename,"w")) {
                $this->log .= "Could not open ".$this->filename."<br />";
                return false;
            }
            $this->contents = $this->formaturl($this->contents, $this->host);
            $this->contents = preg_replace("'<script[^>]*?>.*?</script>'si","",$this->contents);
            //写文件
            if (!@fwrite($fp,$this->contents)) {
                $this->log .= "Could not write to ".$this->filename."<br />";
                fclose($fp);
                return false;
            }
            //关闭文件
            fclose($fp);
            return true;
        }


        /*
            获得文件的时间戳
            参数:
                无
            返回值:
                true:成功, false:失败
        */
        function getFile_ts() {
            $this->log .= "getFile_ts() called<br />";
            if (!file_exists($this->filename)) {
                $this->data_ts = 0;
                $this->log .= $this->filename." does not exist<br />";
                return false;
            }
            $this->data_ts = filemtime($this->filename);
            return true;
        }
        /*
            格式化特殊的Url
            参数:
                无
            返回值:
                格式化后的Url。
        */
        function formaturl($l1, $l2){
            // 查询网页上的所有img,link,a
            if (preg_match_all("/(<img[^>]+src=\"([^\"]+)\"[^>]*>)|(<link[^>]+href=\"([^\"]+)\"[^>]*>)|(<a[^>]+href=\"([^\"]+)\"[^>]*>)|(<img[^>]+src='([^']+)'[^>]*>)|(<a[^>]+href='([^']+)'[^>]*>)/i",$l1,$regs)){
                foreach($regs[0] as $num => $url) {
                    $l1 = str_replace($url, $this->lIIIIl($url, $l2), $l1);
                }
            }
            return $l1;
        }
        /*
            将画面上的二级地址重新解析,以保证画面显示正确
            例如:相对地址/css/sty004.css 会替换为绝对地址 http://xxx.com/css/sty004.css
            参数:
                $l1:要解析的地址
                $l2:需要加上的host前缀
            返回值:
                格式化后的Url。
        */
        function lIIIIl($l1, $l2) {
            if(preg_match("/(.*)(href|src)\=(.+?)( |\/\>|\>).*/i", $l1, $regs)){
                $I2 = $regs[3];
            }
            if(strlen($I2)>0) {
                // 去掉双引号chr(34)和单引号chr(39)
                $I1 = str_replace(chr(34),"",$I2);
                $I1 = str_replace(chr(39),"",$I1);
            } else {
                return $l1;
            }
            $url_parsed = parse_url($l2);
            $scheme = $url_parsed["scheme"];
            if($scheme!="") {
                $scheme = $scheme."://";
            }
            $host = $url_parsed["host"];
            $l3 = $scheme.$host;
            if(strlen($l3)==0)
            {
                return $l1;
            }
            $path = dirname($url_parsed["path"]);
            if($path[0]=="\\") {
                $path="";
            }
            $pos = strpos($I1,"#");
            if($pos>0) {
                $I1 = substr($I1,0,$pos);
            }
            //判断类型
            if(preg_match("/^(http|https|ftp):(\/\/|\\\\)(([\w\/\\\+\-~`@:%])+\.)+([\w\/\\\.\=\?\+\-~`@\':!%#]|(&)|&)+/i",$I1)) {
                return $l1;
                //http类型的url要跳转;
            } elseif($I1[0]=="/") {
            //绝对路径
                $I1 = $l3.$I1;
            } elseif(substr($I1,0,3)=="../") {
            //相对路径
                while(substr($I1,0,3)=="../") {
                    $I1 = substr($I1,strlen($I1)-(strlen($I1)-3),strlen($I1)-3);
                    if(strlen($path)>0){
                        $path = dirname($path);
                    }
                }
                $I1 = $l3.$path."/".$I1;
            } elseif(substr($I1,0,2)=="./") {
                $I1 = $l3.$path.substr($I1,strlen($I1)-(strlen($I1)-1),strlen($I1)-1);
            } elseif(strtolower(substr($I1,0,7))=="mailto:"||strtolower(substr($I1,0,11))=="javascript:") {
                return $l1;
            } else {
                $I1 = $l3.$path."/".$I1;
            }
            return str_replace($I2,"\"$I1\"",$l1);
        }
    }
?>

test.php


<?php
require_once(dirname(__FILE__).'/snap.class.php');
$h = new snap();
$h->fetch($_GET['url']);
//echo $h->log;
echo $h->contents;
?>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值