轉寄一個PHP抓取網頁快照程式

來源:互聯網
上載者:User

轉寄一個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;
?>

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.