Heim > php教程 > PHP源码 > Hauptteil

采集 PHP

PHP中文网
Freigeben: 2016-05-25 17:15:10
Original
1573 Leute haben es durchsucht

充分利用正则的强大字串处理能力,使用简单,功能也比较简单,能满足一般应用,功能也在不断完善中,使用过程:设置一个初始url,添加导航规则,添加采集字段和规则,保存输出即可

<?php
set_time_limit(0);
header("Content-type: text/html; charset=utf-8");
/**
* 采集程序类
* @author  shooting
* @version 1.0.0
*/
class spider
{
/**
* 采集的终端页地址
*
* @var array
*/
var $pages = array();
/**
* 采集结果
*
* @var array
*/
var $result = array();
/**
* 第一层链接页面
*
* @var array
*/
var $startUrls = array();
/**
* 超时时间
*
* @var integer
*/
var $timeout;
/**
* 正在处理的文件内容
*
* @var string
*/
var $httpContent;
/**
* 正在处理的文件头
*
* @var array
*/
var $httpHead=array();
/**
* 自定义的head数组
*
* @var array
*/
var $putHead = array();
/**
* 采集字段与规则数组
*
* @var array
*/
var $field_arr = array();
/**
* 采集层次数
*
* @var interger
*/
var $deep;
/**
* 采集层次结构
*
* @var array
*/
var $layout_arr = array();
/**
* 采集限制条数
*
* @var integer
*/
var $limit = 0;
/**
* 程序运行时间
*
* @var float
*/
var $runtime = 0;
/**
* 被采集页面编码
*
* @var string
*/
var $charset = &#39;UTF-8&#39;;
/**
* 页面引用地址
*
* @var string
*/
var $httpreferer;
var $pagelimit = 0;
var $filepath = &#39;./&#39;;
function spider()
{
  $this->timeout = 30;
}
/**
* 运行采集
*
* @return array
*/
function run()
{
  $begintime = $this->microtime_float();
  $cnt = 1;
  foreach ($this->startUrls as $starturl){
  /**
   * 解析出起始地址中的页码区间
   */
   if(preg_match("~\{(\d+),(\d+)\}~",$starturl,$pagenum)){
    $pagebegin = intval($pagenum[1]);
    $pageend = intval($pagenum[2]);
    for(;$pagebegin<=$pageend;$pagebegin++){
     $starturl = str_replace($pagenum[0],$pagebegin,$starturl);
     $urllists = $this->getLists($this->layout_arr[0][&#39;pattern&#39;],$this->getContent($starturl));
     foreach ($urllists as $url){
      if(($this->limit > 0 && $cnt <= $this->limit)||$this->limit == 0)
      {
       $this->filterContent($this->getContent($url,$starturl));
       $cnt++;
      }
     }
    }
   }else{
    $urllists = $this->getLists($this->layout_arr[0][&#39;pattern&#39;],$this->getContent($starturl));
    foreach ($urllists as $url){
     if(($this->limit > 0 && $cnt <= $this->limit)||$this->limit == 0)
     {
      $this->filterContent($this->getContent($url,$starturl));
      $cnt++;
     }
    }
   }
  }
  $this->runtime =  $this->microtime_float()-$begintime;
  return $this->result;
}
/**
* 从文字段中根据规则提取出url列表
*
* @param string $pattern
* @param string $content
* @return Array
*/
function getLists($pattern=&#39;&#39;,$content=&#39;&#39;)
{
  if(strpos($pattern,&#39;{*}&#39;) === false)return array($pattern);
  $pattern = preg_quote($pattern);
  $pattern = str_replace(&#39;\{\*\}&#39;,&#39;([^\&#39;\">]*)&#39;,$pattern);
  $pattern = "~".$pattern."~is";
  preg_match_all($pattern,$content,$preg_rs);
  return array_unique($preg_rs[0]);
}
/**
* 获取指定url的html内容包括头
*
* @param string $url
* @return string
*/
function getContent($url,$referer = &#39;&#39;)
{
  $url = $this->urlRtoA($url,$referer);
  preg_match("/(http:\/\/)([^:\/]*):?(\d*)(\/?.*)/i",$url,$preg_rs);
  $host = $preg_rs[2];
  $port = empty($preg_rs[3])?80:$preg_rs[3];
  $innerUrl = $preg_rs[4];
  $fsp = fsockopen($host,$port,$errno,$errstr,$this->timeout);
  if(!$fsp)$this->log($errstr.&#39;(&#39;.$errno.&#39;)&#39;);
  $output = "GET $url HTTP/1.0\r\nHost: $host\r\n";
  if(!isset($this->putHead[&#39;Accept&#39;]))$this->putHead[&#39;Accept&#39;]= "*/*";
  if(!isset($this->putHead[&#39;User-Agent&#39;]))$this->putHead[&#39;User-Agent&#39;]=&#39;Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2)&#39;;
  if(!isset($this->putHead[&#39;Refer&#39;])){
   $this->putHead[&#39;Refer&#39;] = ($referer == &#39;&#39;)?&#39;http://&#39;.$host:$referer;
  }
  foreach ($this->putHead as $headname => $headvalue){
   $output .= trim($headname).&#39;: &#39;.trim($headvalue)."\r\n";
  }
  $output .= "Connection: close\r\n\r\n";
  fwrite($fsp,$output);
  $content = &#39;&#39;;
  while (!feof($fsp)) {
        $content .= fgets($fsp,256);
    }
    fclose($fsp);
    $this->getHead($content);
    $this->httpContent = $content;
    if(strtoupper($this->charset) != &#39;UTF-8&#39;){
     $content = iconv($this->charset,&#39;utf-8&#39;,$content);
    }else if(!empty($this->httpHead[&#39;charset&#39;]) && $this->httpHead[&#39;charset&#39;]!=&#39;UTF-8&#39;)
    {
    $content = iconv($this->httpHead[&#39;charset&#39;],&#39;utf-8&#39;,$content);
    }
    $this->httpreferer = $referer;
  return $content;
}
/**
* 按照规则从内容提取所有字段
* @param Array
* @return Array
*/
function filterContent($content=&#39;&#39;)
{
  $rs = array();
  foreach ($this->field_arr as $field => $fieldinfo){
   $rs[$field] = $this->getPregField($fieldinfo,$content);
  }
  $this->result[] = $rs;
}
/**
* 相对路径转化为绝对路径
*
* @param string $relative
* @param string $referer
* @return string
*/
function urlRtoA($relative,$referer)
{
  /**
   * 去除#后面的部分
   */
  $pos = strpos($relative,&#39;#&#39;);
  if($pos >0)$relative = substr($relative,0,$pos);
  /**
   * 检测路径如果是绝对地址直接返回
   */
  if(preg_match("~^(http|ftp)://~i",$relative))
  return $relative;
  /**
   * 解析引用地址,获得协议,主机等信息
   */
  preg_match("~((http|ftp)://([^/]*)(.*/))([^/#]*)~i", $referer, $preg_rs);
  $parentdir = $preg_rs[1];
  $petrol = $preg_rs[2].&#39;://&#39;;
  $host = $preg_rs[3];
  /**
   * 如果以/开头的情况
   */
  if(preg_match("~^/~i",$relative))
   return $petrol.$host.$relative;
  return $parentdir.$relative;
}
/**
* 根据规则提取一个字段
*
* @param string $pattern
* @param string $content
* @return string
*/
function getPregField($fieldinfo,$content)
{
  /**
   * 规则为固定值的情况,直接返回固定值
   */
  if(strpos($fieldinfo[&#39;pattern&#39;],&#39;{&#39;.$fieldinfo[&#39;field&#39;].&#39;}&#39;) === false)
  return $fieldinfo[&#39;pattern&#39;];
  if($fieldinfo[&#39;isregular&#39;] == &#39;true&#39;){
   $pattern = $fieldinfo[&#39;pattern&#39;];
   $pattern = str_replace(&#39;{&#39;.$fieldinfo[&#39;field&#39;].&#39;}&#39;,&#39;(?P<&#39;.$fieldinfo[&#39;field&#39;].&#39;>.*?)&#39;,$pattern);
  }else{
   $pattern = preg_quote($fieldinfo[&#39;pattern&#39;]);
   $pattern = str_replace(&#39;\{&#39;.$fieldinfo[&#39;field&#39;].&#39;\}&#39;,&#39;(?P<&#39;.$fieldinfo[&#39;field&#39;].&#39;>.*?)&#39;,$pattern);
  }
  $pattern = "~".$pattern."~is";
  preg_match($pattern,$content,$preg_rs);
  $fieldresult = $preg_rs[$fieldinfo[&#39;field&#39;]];
  /**
   * 去掉换行符
   */
  $fieldresult = preg_replace("~[\r\n]*~is",&#39;&#39;,$fieldresult);
  /**
   * 对采集到的结果根据规则再进行二次替换处理
   */
  $replace_arr = $fieldinfo[&#39;replace&#39;];
  if(is_array($replace_arr)){
   $replace_arr[0] = "~".$replace_arr[0]."~s";
   $fieldresult = preg_replace($replace_arr[0],$replace_arr[1],$fieldresult);
  }
  /**
   * 针对有下一页的字段递归采集
   */
  if($this->pagelimit == 0){
  if($fieldinfo[&#39;nextpage&#39;] != &#39;&#39;){
   $pattern = $fieldinfo[&#39;nextpage&#39;];
   $pattern = str_replace(&#39;{nextpage}&#39;,&#39;(?P<nextpage>[^\&#39;\">]*?)&#39;,$pattern);
   $pattern = "~".$pattern."~is";
   if(preg_match($pattern,$content,$preg_rs) && $preg_rs[&#39;nextpage&#39;] != &#39;&#39;){
    $fieldresult .= $this->getPregField($fieldinfo,$this->getContent($preg_rs[&#39;nextpage&#39;],$this->httpreferer));
   }
  }
  }
  if(!empty($fieldinfo[&#39;callback&#39;]))$fieldresult = $fieldinfo[&#39;callback&#39;]($fieldresult);
  return $fieldresult;
}
/**
* 添加一个采集字段和规则
*
* @param string $field
* @param string $pattern
*/
function addField($field,$pattern,$replace_arr=&#39;&#39;,$isregular=&#39;false&#39;,$nextpage = &#39;&#39;,$callback=&#39;&#39;)
{
  $rs = array(
    &#39;field&#39; => $field,
    &#39;pattern&#39; => $pattern,
    &#39;replace&#39; => $replace_arr,
    &#39;isregular&#39; => $isregular,
    &#39;nextpage&#39; => $nextpage,
    &#39;callback&#39;=>$callback
    );
  $this->field_arr[$field] =$rs;
}
/**
* 输出
*
*/
function output()
{
  echo "The result is:<br/>";
  echo "runtime :$this->runtime S<br/><pre class="brush:php;toolbar:false">";
  print_r($this->result);
  echo "
"; } /** * 输出到XLS文件 * * @param string $file */ function saveXls($file = 'spider_result.xls') { $fp = fopen($file,'w'); if($fp){ foreach ($this->result as $result) { $line = implode("\t",$result)."\n"; fputs($fp,$line); } } fclose($fp); echo 'The result has been saved to '.$file.'.
Cost time:'.$this->runtime; } function saveSql($table = 'spider_result',$file = 'spider_result.sql') { $fp = fopen($file,'w'); if($fp){ foreach($this->field_arr as $fieldinfo){ $sql_key .= ', `'.$fieldinfo['field'].'`'; } $sql_key = substr($sql_key,1); foreach ($this->result as $result) { $sql_value = array(); foreach ($result as $key => $value){ $sql_value[] = "'".$this->addslash($value)."'"; } $line ="INSERT INTO `$table` ( $sql_key ) VALUES (".join(', ',$sql_value).");\r\n"; fputs($fp,$line); } } fclose($fp); echo 'The result has been saved to '.$file.'.
Cost time:'.$this->runtime; } /** * 取得响应内容的头部信息 * * @param string $content * @return array */ function getHead($content) { $head = explode("\r\n\r\n",$content); $head = $head[0]; // echo $head; if(!preg_match("~charset\=(.*)\r\n~i",$head,$preg_rs)) preg_match('~charset=([^\"\']*)~i',$content,$preg_rs); $this->httpHead['charset'] = strtoupper(trim($preg_rs[1])); // preg_match("~charset\=(.*)~i",$head,$preg_rs); return $this->httpHead; } /** * 设置采集页面的编码 * 在程序不能自动识别的情况下采集前要手动调用此函数 * * @param string $charset */ function setCharset($charset){ $this->charset = strtoupper($charset); } /** * 设置第一层链接页面地址 * * @param array $url_arr */ function setStartUrls($url_arr) { $this->startUrls = $url_arr; } /** * 增加一个第一层链接页面地址 * * @param string $url */ function addStartUrl($url) { $this->startUrls[] = $url; } /** * 添加一个采集层次 * * @param integer $deep * @param string $layout * @param boolean $isSimple * @param boolean $isPageBreak * @param string $pattern */ function addLayer($deep,$layout,$pattern = '',$isSimple = 'false',$isPageBreak = 'false') { $this->layout_arr[$deep] = array( 'layout'=>$layout, 'isSimple'=>$isSimple, 'isPageBreak'=>$isPageBreak, 'pattern'=>$pattern ); } /** * 自定义head * @param string $namespace * @param string $value */ function setHead($name,$value) { $this->putHead[$name] = $value; } /** * 清除html代码 * @param string $content; * @param string $cleartags * @return string */ function clearHtml($content,$cleartags = 'p') { $cleartags_arr = explode('|',$cleartags); foreach ($cleartags_arr as $cleartag){ $pattern = '~<\/?'.$cleartag.'[^>]*>~is'; $content = preg_replace($pattern,'',$content); } return $content; } /** * 日志 * */ function log($str) { echo $str."
\n"; } /** * 获取采集运行时间 * * @return float */ function getRuntime() { return $this->runtime; } function microtime_float() { list($usec, $sec) = explode(" ", microtime()); return ((float)$usec + (float)$sec); } function addslash($string) { return addslashes($string); } } $spider = new spider(); $spider->addStartUrl('http://hi.baidu.com/shuntian/blog/index/{0,5}'); $spider->setCharset('gb2312'); $spider->addLayer(0,'list','/shuntian/blog/item/{*}.html'); $spider->addField('title','{title}',array('_顺者的天空-shooting's sky ','')); $spider->addField('body','

{body}

'); $spider->addField('author','shooting'); $spider->run(); $spider->saveSql();
Nach dem Login kopieren

 以上就是采集的内容,更多相关内容请关注PHP中文网(www.php.cn)!


Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Empfehlungen
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage