0

0

采集 PHP

PHP中文网

PHP中文网

发布时间:2016-05-25 17:15:10

|

1870人浏览过

|

来源于php中文网

原创

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

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]['pattern'],$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]['pattern'],$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='',$content='')
{
  if(strpos($pattern,'{*}') === false)return array($pattern);
  $pattern = preg_quote($pattern);
  $pattern = str_replace('\{\*\}','([^\'\">]*)',$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 = '')
{
  $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.'('.$errno.')');
  $output = "GET $url HTTP/1.0\r\nHost: $host\r\n";
  if(!isset($this->putHead['Accept']))$this->putHead['Accept']= "*/*";
  if(!isset($this->putHead['User-Agent']))$this->putHead['User-Agent']='Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2)';
  if(!isset($this->putHead['Refer'])){
   $this->putHead['Refer'] = ($referer == '')?'http://'.$host:$referer;
  }
  foreach ($this->putHead as $headname => $headvalue){
   $output .= trim($headname).': '.trim($headvalue)."\r\n";
  }
  $output .= "Connection: close\r\n\r\n";
  fwrite($fsp,$output);
  $content = '';
  while (!feof($fsp)) {
        $content .= fgets($fsp,256);
    }
    fclose($fsp);
    $this->getHead($content);
    $this->httpContent = $content;
    if(strtoupper($this->charset) != 'UTF-8'){
     $content = iconv($this->charset,'utf-8',$content);
    }else if(!empty($this->httpHead['charset']) && $this->httpHead['charset']!='UTF-8')
    {
    $content = iconv($this->httpHead['charset'],'utf-8',$content);
    }
    $this->httpreferer = $referer;
  return $content;
}
/**
* 按照规则从内容提取所有字段
* @param Array
* @return Array
*/
function filterContent($content='')
{
  $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,'#');
  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].'://';
  $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['pattern'],'{'.$fieldinfo['field'].'}') === false)
  return $fieldinfo['pattern'];
  if($fieldinfo['isregular'] == 'true'){
   $pattern = $fieldinfo['pattern'];
   $pattern = str_replace('{'.$fieldinfo['field'].'}','(?P<'.$fieldinfo['field'].'>.*?)',$pattern);
  }else{
   $pattern = preg_quote($fieldinfo['pattern']);
   $pattern = str_replace('\{'.$fieldinfo['field'].'\}','(?P<'.$fieldinfo['field'].'>.*?)',$pattern);
  }
  $pattern = "~".$pattern."~is";
  preg_match($pattern,$content,$preg_rs);
  $fieldresult = $preg_rs[$fieldinfo['field']];
  /**
   * 去掉换行符
   */
  $fieldresult = preg_replace("~[\r\n]*~is",'',$fieldresult);
  /**
   * 对采集到的结果根据规则再进行二次替换处理
   */
  $replace_arr = $fieldinfo['replace'];
  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['nextpage'] != ''){
   $pattern = $fieldinfo['nextpage'];
   $pattern = str_replace('{nextpage}','(?P[^\'\">]*?)',$pattern);
   $pattern = "~".$pattern."~is";
   if(preg_match($pattern,$content,$preg_rs) && $preg_rs['nextpage'] != ''){
    $fieldresult .= $this->getPregField($fieldinfo,$this->getContent($preg_rs['nextpage'],$this->httpreferer));
   }
  }
  }
  if(!empty($fieldinfo['callback']))$fieldresult = $fieldinfo['callback']($fieldresult);
  return $fieldresult;
}
/**
* 添加一个采集字段和规则
*
* @param string $field
* @param string $pattern
*/
function addField($field,$pattern,$replace_arr='',$isregular='false',$nextpage = '',$callback='')
{
  $rs = array(
    'field' => $field,
    'pattern' => $pattern,
    'replace' => $replace_arr,
    'isregular' => $isregular,
    'nextpage' => $nextpage,
    'callback'=>$callback
    );
  $this->field_arr[$field] =$rs;
}
/**
* 输出
*
*/
function output()
{
  echo "The result is:
"; echo "runtime :$this->runtime S
";
  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 = '~]*>~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();

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

Browse AI
Browse AI

AI驱动的网页内容抓取和数据采集工具

下载
PHP速学教程(入门到精通)
PHP速学教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
Golang处理数据库错误教程合集
Golang处理数据库错误教程合集

本专题整合了Golang数据库错误处理方法、技巧、管理策略相关内容,阅读专题下面的文章了解更多详细内容。

2

2026.02.06

java多线程方法汇总
java多线程方法汇总

本专题整合了java多线程面试题、实现函数、执行并发相关内容,阅读专题下面的文章了解更多详细内容。

0

2026.02.06

1688阿里巴巴货源平台入口与批发采购指南
1688阿里巴巴货源平台入口与批发采购指南

本专题整理了1688阿里巴巴批发进货平台的最新入口地址与在线采购指南,帮助用户快速找到官方网站入口,了解如何进行批发采购、货源选择以及厂家直销等功能,提升采购效率与平台使用体验。

90

2026.02.06

快手网页版入口与电脑端使用指南 快手官方短视频观看入口
快手网页版入口与电脑端使用指南 快手官方短视频观看入口

本专题汇总了快手网页版的最新入口地址和电脑版使用方法,详细提供快手官网直接访问链接、网页端操作教程,以及如何无需下载安装直接观看短视频的方式,帮助用户轻松浏览和观看快手短视频内容。

15

2026.02.06

C# 多线程与异步编程
C# 多线程与异步编程

本专题深入讲解 C# 中多线程与异步编程的核心概念与实战技巧,包括线程池管理、Task 类的使用、async/await 异步编程模式、并发控制与线程同步、死锁与竞态条件的解决方案。通过实际项目,帮助开发者掌握 如何在 C# 中构建高并发、低延迟的异步系统,提升应用性能和响应速度。

10

2026.02.06

Python 微服务架构与 FastAPI 框架
Python 微服务架构与 FastAPI 框架

本专题系统讲解 Python 微服务架构设计与 FastAPI 框架应用,涵盖 FastAPI 的快速开发、路由与依赖注入、数据模型验证、API 文档自动生成、OAuth2 与 JWT 身份验证、异步支持、部署与扩展等。通过实际案例,帮助学习者掌握 使用 FastAPI 构建高效、可扩展的微服务应用,提高服务响应速度与系统可维护性。

6

2026.02.06

JavaScript 异步编程与事件驱动架构
JavaScript 异步编程与事件驱动架构

本专题深入讲解 JavaScript 异步编程与事件驱动架构,涵盖 Promise、async/await、事件循环机制、回调函数、任务队列与微任务队列、以及如何设计高效的异步应用架构。通过多个实际示例,帮助开发者掌握 如何处理复杂异步操作,并利用事件驱动设计模式构建高效、响应式应用。

7

2026.02.06

java连接字符串方法汇总
java连接字符串方法汇总

本专题整合了java连接字符串教程合集,阅读专题下面的文章了解更多详细操作。

25

2026.02.05

java中fail含义
java中fail含义

本专题整合了java中fail的含义、作用相关内容,阅读专题下面的文章了解更多详细内容。

28

2026.02.05

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
TypeScript 教程
TypeScript 教程

共19课时 | 2.8万人学习

Pandas 教程
Pandas 教程

共15课时 | 1万人学习

麻省理工大佬Python课程
麻省理工大佬Python课程

共34课时 | 5.3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号