程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> 關於PHP編程 >> DedeHttpDown PHP遠程下載網頁的類,增強版 2013-1-17修改

DedeHttpDown PHP遠程下載網頁的類,增強版 2013-1-17修改

編輯:關於PHP編程

1)新增遠程主機判斷,節約服務器資源。避免遠程主機不存在的時候仍舊fsockopen,導致的死機占用服務器CPU   (2)新增響應401的判斷和支持。   (3)增加對json返回文本的支持。   (4)日志的生成,如果設置了DEBUG_LEVEL且為TRUE則會對每次遠程下載做日志。   (5)獲取字節的限定dataLimit,節約服務器資源。 (6)修改日期:2013-1-17     如果還有更好的方法建議,可以隨時聯系我本人。[email protected]        [php]   <?php   /**   * 織夢HTTP下載類   *   * @version        $Id: dedehttpdown.class.php 1 11:42 2010年7月6日Z tianya $   * @package        DedeCMS.Libraries   * @copyright      Copyright (c) 2007 - 2010, DesDev, Inc.   * @modify author  [email protected]   * @license        http://help.dedecms.com/usersguide/license.html   * @link           http://www.dedecms.com   */   @set_time_limit(0);      class DedeHttpDown   {       var $m_url = '';       var $m_urlpath = '';       var $m_scheme = 'http';       var $m_host = '';       var $m_port = '80';       var $m_user = '';       var $m_pass = '';       var $m_path = '/';       var $m_query = '';       var $m_fp = '';       var $m_error = '';       var $m_httphead = '';       var $m_html = '';       var $dataLimit = 0;       var $m_puthead = '';       var $BaseUrlPath = '';       var $HomeUrl = '';       var $reTry = 0;       var $JumpCount = 0;          /**       *  初始化系統       *       * @access    public       * @param     string    $url   需要下載的地址       * @return    string       */       function PrivateInit($url)       {           if($url=='') {               return ;           }           $urls = '';           $urls = @parse_url($url);           $this->m_url = $url;           if(is_array($urls))           {               $this->m_host = $urls["host"];               if(!emptyempty($urls["scheme"]))               {                   $this->m_scheme = $urls["scheme"];               }               if(!emptyempty($urls["user"]))               {                   $this->m_user = $urls["user"];               }               if(!emptyempty($urls["pass"]))               {                   $this->m_pass = $urls["pass"];               }               if(!emptyempty($urls["port"]))               {                   $this->m_port = $urls["port"];               }               if(!emptyempty($urls["path"]))               {                   $this->m_path = $urls["path"];               }               $this->m_urlpath = $this->m_path;               if(!emptyempty($urls["query"]))               {                   $this->m_query = $urls["query"];                   $this->m_urlpath .= "?".$this->m_query;               }               $this->HomeUrl = $urls["host"];               $this->BaseUrlPath = $this->HomeUrl.$urls["path"];               $this->BaseUrlPath = preg_replace("/\/([^\/]*)\.(.*)$/","/",$this->BaseUrlPath);               $this->BaseUrlPath = preg_replace("/\/$/","",$this->BaseUrlPath);           }       }          /**       *  重設各參數       *       * @access    public       * @return    void       */       function ResetAny()       {           $this->m_url = "";           $this->m_urlpath = "";           $this->m_scheme = "http";           $this->m_host = "";           $this->m_port = "80";           $this->m_user = "";           $this->m_pass = "";           $this->m_path = "/";           $this->m_query = "";           $this->m_error = "";       }          /**       *  打開指定網址       *       * @access    public       * @param     string    $url   地址       * @param     string    $requestType   請求類型       * @return    string       */       function OpenUrl($url,$requestType="GET")       {              $this->ResetAny();           $this->JumpCount = 0;           $this->m_httphead = Array() ;           $this->m_html = '';           $this->dataLimit = 0;           $this->reTry = 0;           $this->Close();              //初始化系統           $this->PrivateInit($url);           $this->PrivateStartSession($requestType);       }          /**       *  轉到303重定向網址       *       * @access    public       * @param     string   $url   地址       * @return    string       */       function JumpOpenUrl($url)       {           $this->ResetAny();           $this->JumpCount++;           $this->m_httphead = Array() ;           $this->m_html = "";           $this->Close();              //初始化系統           $this->PrivateInit($url);           $this->PrivateStartSession('GET');       }          /**       *  獲得某操作錯誤的原因       *       * @access    public       * @return    void       */       function printError()       {           echo "錯誤信息:".$this->m_error;           echo "<br/>具體返回頭:<br/>";           foreach($this->m_httphead as $k=>$v){ echo "$k => $v <br/>\r\n"; }       }          /**       *  判別用Get方法發送的頭的應答結果是否正確       *       * @access    public       * @return    bool       */       function IsGetOK()       {           if( preg_match("/^2/",$this->GetHead("http-state")) )           {               return TRUE;           }           else           {               $this->m_error .= $this->GetHead("http-state")." - ".$this->GetHead("http-describe")."<br/>";               return FALSE;           }       }          /**       *  看看返回的網頁是否是text類型       *       * @access    public       * @return    bool       */       function IsText()       {           if( preg_match("/^(2|401)/",$this->GetHead("http-state")) && preg_match("/text|xml|json/i",$this->GetHead("content-type")) )           {               return TRUE;           } else {               $this->m_error .= "內容為非文本類型或網址重定向<br/>";               return FALSE;           }       }          /**       *  判斷返回的網頁是否是特定的類型       *       * @access    public       * @param     string   $ctype   內容類型       * @return    string       */       function IsContentType($ctype)       {           if(preg_match("/^2/",$this->GetHead("http-state"))           && $this->GetHead("content-type")==strtolower($ctype))           {    return TRUE; }           else           {               $this->m_error .= "類型不對 ".$this->GetHead("content-type")."<br/>";               return FALSE;           }       }          /**       *  用Http協議下載文件       *       * @access    public       * @param     string    $savefilename  保存文件名稱       * @return    string       */       function SaveToBin($savefilename)       {           if(!$this->IsGetOK())           {               return FALSE;           }           if(@feof($this->m_fp))           {               $this->m_error = "連接已經關閉!"; return FALSE;           }           $fp = fopen($savefilename,"w");           while(!feof($this->m_fp))           {               fwrite($fp, fread($this->m_fp, 1024));           }           fclose($this->m_fp);           fclose($fp);           return TRUE;       }          /**       *  保存網頁內容為Text文件       *       * @access    public       * @param     string    $savefilename  保存文件名稱       * @return    string       */       function SaveToText($savefilename)       {           if($this->IsText())           {               $this->SaveBinFile($savefilename);           }           else           {               return "";           }       }          /**       *  用Http協議獲得一個網頁的內容       *       * @access    public       * @return    string       */       function GetHtml()       {           $tm1 = microtime(true);           if(!$this->IsText())           {               return '';           }           if($this->m_html!='')           {               return $this->m_html;           }           if(!$this->m_fp||@feof($this->m_fp))           {               return '';           }           while(!feof($this->m_fp))           {               $this->m_html .= fgets($this->m_fp,256);               if($this->dataLimit > 0 && strlen($this->m_html) > $this->dataLimit) break;           }           @fclose($this->m_fp);              $tm2 = microtime(true);           $log = "\ntm2-tm1 = ".($tm2-$tm1);           $log.= "\n".$this->m_html;           $this->log_write('GetHtml',$log);              return $this->m_html;       }          /**       *  開始HTTP會話       *       * @access    public       * @param     string    $requestType    請求類型       * @return    string       */       function PrivateStartSession($requestType="GET")       {           if(!$this->PrivateOpenHost())           {               $this->m_error .= "打開遠程主機出錯!";               return FALSE;           }           $this->reTry++;           if($this->GetHead("http-edition")=="HTTP/1.1")           {               $httpv = "HTTP/1.1";           }           else           {               $httpv = "HTTP/1.0";           }           $ps = explode('?',$this->m_urlpath);              $headString = '';              //發送固定的起始請求頭GET、Host信息           if($requestType=="GET")           {               $headString .= "GET ".$this->m_urlpath." $httpv\r\n";           }           else           {               $headString .= "POST ".$ps[0]." $httpv\r\n";           }              if($this->m_user || $this->m_pass)           {               $headString .= "Authorization: Basic ".base64_encode($this->m_user.":".$this->m_pass)."\r\n";           }           $this->m_puthead["Host"] = $this->m_host;              //發送用戶自定義的請求頭           if(!isset($this->m_puthead["User-Agent"]))           {               $this->m_puthead["User-Agent"] = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2)";           }           if(!isset($this->m_puthead["Refer"]))           {               $this->m_puthead["Refer"] = "http://".$this->m_puthead["Host"];           }              /* add on 2012-12-19 */          $headString.="Connection:keep-alive\r\n";          $headString.="Accept-Language:zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3\r\n";          $headString.="Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";              foreach($this->m_puthead as $k=>$v)           {               $k = trim($k);               $v = trim($v);               if($k!=""&&$v!="")               {                   $headString .= "$k: $v\r\n";               }           }           fputs($this->m_fp, $headString);           if($requestType=="POST")           {               $postdata = "";               if(count($ps)>1)               {                   for($i=1;$i<count($ps);$i++)                   {                       $postdata .= $ps[$i];                   }               }               else               {                   $postdata = "OK";               }               $plen = strlen($postdata);               fputs($this->m_fp,"Content-Type: application/x-www-form-urlencoded\r\n");               fputs($this->m_fp,"Content-Length: $plen\r\n");           }              //發送固定的結束請求頭           //HTTP1.1協議必須指定文檔結束後關閉鏈接,否則讀取文檔時無法使用feof判斷結束           if($httpv=="HTTP/1.1")           {               fputs($this->m_fp,"Connection: Close\r\n\r\n");           }           else           {               fputs($this->m_fp,"\r\n");           }           if($requestType=="POST")           {               fputs($this->m_fp,$postdata);           }              //獲取應答頭狀態信息           $httpstas = explode(" ",fgets($this->m_fp,256));           $this->m_httphead["http-edition"] = trim($httpstas[0]);           $this->m_httphead["http-state"] = trim($httpstas[1]);           $this->m_httphead["http-describe"] = "";           for($i=2;$i<count($httpstas);$i++)           {               $this->m_httphead["http-describe"] .= " ".trim($httpstas[$i]);           }              //獲取詳細應答頭           while(!feof($this->m_fp))           {               $line = trim(fgets($this->m_fp,256));               if($line == "")               {                   break;               }               $hkey = "";               $hvalue = "";               $v = 0;               for($i=0;$i<strlen($line);$i++)               {                   if($v==1)                   {                       $hvalue .= $line[$i];                   }                   if($line[$i]==":")                   {                       $v = 1;                   }                   if($v==0)                   {                       $hkey .= $line[$i];                   }               }               $hkey = trim($hkey);               if($hkey!="")               {                   $this->m_httphead[strtolower($hkey)] = trim($hvalue);               }           }              //如果連接被不正常關閉,重試           if(feof($this->m_fp))           {               if($this->reTry > 10)               {                   return FALSE;               }               $this->PrivateStartSession($requestType);           }              //判斷是否是3xx開頭的應答           if(preg_match("/^3/",$this->m_httphead["http-state"]))           {               if($this->JumpCount > 3)               {                   return;               }               if(isset($this->m_httphead["location"]))               {                   $newurl = $this->m_httphead["location"];                   if(preg_match("/^http/i",$newurl))                   {                       $this->JumpOpenUrl($newurl);                   }                   else                   {                       $newurl = $this->FillUrl($newurl);                       $this->JumpOpenUrl($newurl);                   }               }               else               {                   $this->m_error = "無法識別的答復!";               }           }       }          /**        *  獲得一個Http頭的值        *        * @access    public        * @param     string    $headname   頭文件名稱        * @return    string        */       function GetHead($headname)       {           $headname = strtolower($headname);           return isset($this->m_httphead[$headname]) ? $this->m_httphead[$headname] : '';       }          /**       *  設置Http頭的值       *       * @access    public       * @param     string   $skey  鍵       * @param     string   $svalue  值       * @return    string       */       function SetHead($skey,$svalue)       {           $this->m_puthead[$skey] = $svalue;       }          /**       *  打開連接       *       * @access    public       * @return    bool       */       function PrivateOpenHost()       {           if($this->m_host=="")           {               return FALSE;           }              if(function_exists('checkdnsrr') && !checkdnsrr($this->m_host,'A') && !checkdnsrr($this->m_host,'CNAME'))           {               $this->m_error = '遠程主機'.$this->m_host.'不存在!checkdnsrr !';               return FALSE;           }           $errno = "";           $errstr = "";           $this->m_fp = @fsockopen($this->m_host, $this->m_port, $errno, $errstr,10);           if(!$this->m_fp)           {               $this->m_error = $errstr;               return FALSE;           }           else           {               return TRUE;           }       }          /**       *  關閉連接       *       * @access    public       * @return    void       */       function Close()       {           @fclose($this->m_fp);       }          /**       *  補全相對網址       *       * @access    public       * @param     string   $surl  需要不全的地址       * @return    string       */       function FillUrl($surl)       {           $i = 0;           $dstr = "";           $pstr = "";           $okurl = "";           $pathStep = 0;           $surl = trim($surl);           if($surl=="")           {               return "";           }           $pos = strpos($surl,"#");           if($pos>0)           {               $surl = substr($surl,0,$pos);           }           if($surl[0]=="/")           {               $okurl = "http://".$this->HomeUrl.$surl;           }           else if($surl[0]==".")           {               if(strlen($surl)<=1)               {                   return "";               }               else if($surl[1]=="/")               {                   $okurl = "http://".$this->BaseUrlPath."/".substr($surl,2,strlen($surl)-2);               }               else               {                   $urls = explode("/",$surl);                   foreach($urls as $u)                   {                       if($u=="..")                       {                           $pathStep++;                       }                       else if($i<count($urls)-1)                       {                           $dstr .= $urls[$i]."/";                       }                       else                       {                           $dstr .= $urls[$i];                       }                       $i++;                   }                   $urls = explode("/",$this->BaseUrlPath);                   if(count($urls) <= $pathStep)                   {                       return "";                   }                   else                   {                       $pstr = "http://";                       for($i=0;$i<count($urls)-$pathStep;$i++)                       {                           $pstr .= $urls[$i]."/";                       }                       $okurl = $pstr.$dstr;                   }               }           }           else           {               if(strlen($surl)<7)               {                   $okurl = "http://".$this->BaseUrlPath."/".$surl;               }               else if(strtolower(substr($surl,0,7))=="http://")               {                   $okurl = $surl;               }               else               {                   $okurl = "http://".$this->BaseUrlPath."/".$surl;               }           }           $okurl = preg_replace("/^(http:\/\/)/i","",$okurl);           $okurl = preg_replace("/\/{1,}/", "/", $okurl);           return "http://".$okurl;       }             function log_write($funcname,$message)       {           if(!(defined('DEBUG_LEVEL') && DEBUG_LEVEL == TRUE)) return ;              $log = "\n".date("Y-M-d H:i:s ").get_current_user()."[".getmypid()."]";           $log.= "\n".$this->m_url."\n".str_repeat('------', 10)."\n".$message;              $path = $funcname.' '.date('Y m d H i s ').preg_replace('/([\W]+|\s+)/i', ' ', $this->m_url);           if(strlen($path) > 250) $path = substr($path,0,250);              $dir = DEDEDATA.'/httpdownlog';           if(!is_dir($dir) && !mkdir($dir)) exit('Can not make dir '.$dir);              $path = $dir.'/'.$path;           if(!file_exists($path)) touch($path);              $fp = fopen($path,'a+');           flock($fp, LOCK_EX);           fputs($fp, "PATH:".$path."\nREAL:".realpath($path)."\nMSSG:".$log);           fclose($fp);              return TRUE;       }      }//End Class       使用方法:     [php]   $dhd = new DeDeHttpDown();   $dhd->OpenUrl($Rs['wurl']);   $dhd->dataLimit = 5120;   $dhd->m_puthead["Refer"] = $Rs['wurl'];   $filecnt = trim($dhd->GetHtml());           存在未解決的問題:   (1)假如域名是綁定了A記錄和CNAME,有ip指向,但是IP地址是不存在的或者虛假的,程序仍舊會繼續獲取。   (2)PHP的fsockopen 裡面的time out貌似根本就沒有起作用。設置了10s超時,但是根本就是執行到程序time out 為止。     如果好的方法建議,可以隨時聯系我本人。[email protected]   

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved