PHP多线程批量采集下载美女图片的实现代码(续)


Posted in PHP onJune 03, 2013

个人认为影响的原因:
匹配到的图片url并不是有效的url,文中只是简单的判断是否是相对路径,但是有些url是失效的
解决办法:就是新增判断是否是真实有效url的图片

/**
 * 
 *判断url是否有效 
 *@param $url string
 *@return boole 
 */
function relUrl($url){
 if(substr($url,0,4)=='http'){
  $array = get_headers($url,true);
  if(count($array)>0 && is_array($array)){
   if(preg_match('/200/', $array[0])){
    unset($array);
    return true;
   }else{
    unset($array);
    return false;
   }
  }else{
   unset($array);
   return false;
  }
 }else{
  return false;
 }
}

主要使用get_headers函数,获取http请求信息,判断服务端反应状态(200)判断url是否真实有效。

再次测试采集图片
结果比以前还要糟糕,运行的更慢了。

测试的原因就是:
get_headers函数虽然可以判断url是否真实有效,但是假如遇到很慢的url资源,因为get-heades请求没有时间限制,导致这个线程被占用,后续的请求被阻塞
file_get_content函数和上面的原因一样,由于某些慢的url资源都长期占用,阻塞后面的进程被占用,长期阻塞,cpu占用也会增高
解决办法;
使用curl的多线程,另外curl可以设置请求时间,遇到很慢的url资源,可以果断的放弃,这样没有阻塞,另外有多线程请求,效率应该比较高,参考:《CURL的学习和应用[附多线程]》,我们再来测试一下;

核心代码:

/** 
     * curl 多线程 
     *  
     * @param array $array 并行网址 
     * @param int $timeout 超时时间
     * @return mix 
     */
 public function Curl_http($array,$timeout='15'){
      $res = array();      $mh = curl_multi_init();//创建多个curl语柄

      foreach($array as $k=>$url){
          $conn[$k]=curl_init($url);//初始化
          curl_setopt($conn[$k], CURLOPT_TIMEOUT, $timeout);//设置超时时间
          curl_setopt($conn[$k], CURLOPT_USERAGENT, 'Mozilla/5.0 (compatible; MSIE 5.01; Windows NT 5.0)');
          curl_setopt($conn[$k], CURLOPT_MAXREDIRS, 7);//HTTp定向级别 ,7最高
          curl_setopt($conn[$k], CURLOPT_HEADER, false);//这里不要header,加块效率
          curl_setopt($conn[$k], CURLOPT_FOLLOWLOCATION, 1); // 302 redirect
          curl_setopt($conn[$k], CURLOPT_RETURNTRANSFER,1);//要求结果为字符串且输出到屏幕上          
    curl_setopt($conn[$k], CURLOPT_HTTPGET, true);
          curl_multi_add_handle ($mh,$conn[$k]);
      }
       //防止死循环耗死cpu 这段是根据网上的写法
          do {
              $mrc = curl_multi_exec($mh,$active);//当无数据,active=true
          } while ($mrc == CURLM_CALL_MULTI_PERFORM);//当正在接受数据时
          while ($active and $mrc == CURLM_OK) {//当无数据时或请求暂停时,active=true
              if (curl_multi_select($mh) != -1) {
                  do {
                      $mrc = curl_multi_exec($mh, $active);
                  } while ($mrc == CURLM_CALL_MULTI_PERFORM);
              }
          }
      foreach ($array as $k => $url) {
            if(!curl_errno($conn[$k])){
             $data[$k]=curl_multi_getcontent($conn[$k]);//数据转换为array
             $header[$k]=curl_getinfo($conn[$k]);//返回http头信息
             curl_close($conn[$k]);//关闭语柄
             curl_multi_remove_handle($mh  , $conn[$k]);   //释放资源 
            }else{
             unset($k,$url);
            }
          }
          curl_multi_close($mh);
          return $data;
   }
//参数接收
$callback = $_GET['callback'];
$hrefs = $_GET['hrefs'];
$urlarray = explode(',',trim($hrefs,','));
$date = date('Ymd',time());
//实例化
$img = new HttpImg();
$stime = $img->getMicrotime();//开始时间
$data = $img->Curl_http($urlarray,'20');//列表数据
mkdir('./img/'.$date,0777);
foreach ((array)$data as $k=>$v){
 preg_match_all("/(href|src)=(["|']?)([^ "'>]+.(jpg|png|PNG|JPG|gif))\2/i", $v, $matches[$k]);
 if(count($matches[$k][3])>0){
  $dataimg = $img->Curl_http($matches[$k][3],'20');//全部图片数据二进制
  $j = 0;
  foreach ((array)$dataimg as $kk=>$vv){
   if($vv !=''){
    $rand = rand(1000,9999);
    $basename = time()."_".$rand.".".jpg;//保存为jpg格式的文件
    $fname = './img/'.$date."/"."$basename";
    file_put_contents($fname, $vv);   
    $j++;
    echo "创建第".$j."张图片"."$fname"."<br/>";
   }else{
    unset($kk,$vv);
   }
  }
 }else{
  unset($matches);
 }
}
$etime = $img->getMicrotime();//结束时间
echo "用时".($etime-$stime)."秒";
exit;

测试一下效果
PHP多线程批量采集下载美女图片的实现代码(续)
337张图片用时260秒左右,基本上可以做到一秒内就可以采集一张的效果,而且发现图片越到优势采集速度越明显。

我们可以看一下文件命名:也就可以做到同一时刻可以生成10张图片,

由于采用了20秒请求的时间限制,有些图片生成后有明显不全,也就是图片资源在20秒内未能完全采集,这个时间大家可以自行设置。

PHP 相关文章推荐
Windows下PHP的任意文件执行漏洞
Oct 09 PHP
粗略计算在线时间,bug:ip相同
Dec 09 PHP
php不用内置函数对数组排序的两个算法代码
Feb 08 PHP
php trim 去除空字符的定义与语法介绍
May 31 PHP
php中定义网站根目录的常用方法
Aug 08 PHP
PHP学习笔记之一
Jan 17 PHP
表格展示无限级分类(PHP版)
Aug 21 PHP
PHP中使用smarty生成静态文件的例子
Apr 24 PHP
PHP编程基本语法快速入门手册
Jan 07 PHP
Laravel 批量更新多条数据的示例
Nov 27 PHP
PHP耦合设计模式实例分析
Aug 08 PHP
ThinkPHP5.0框架实现切换数据库的方法分析
Oct 30 PHP
获取php页面执行时间,数据库读写次数,函数调用次数等(THINKphp)
Jun 03 #PHP
php变量作用域的深入解析
Jun 03 #PHP
CURL的学习和应用(附多线程实现)
Jun 03 #PHP
php魔术方法与魔术变量、内置方法与内置变量的深入分析
Jun 03 #PHP
PHP flush()与ob_flush()的区别详解
Jun 03 #PHP
PHP导出EXCEL快速开发指南--PHPEXCEL的使用详解
Jun 03 #PHP
PHP Cookie的使用教程详解
Jun 03 #PHP
You might like
实用函数9
2007/11/08 PHP
MYSQL 小技巧 -- LAST_INSERT_ID
2009/11/24 PHP
PHP 之Section与Cookie使用总结
2012/09/14 PHP
探讨多键值cookie(php中cookie存取数组)的详解
2013/06/06 PHP
大家须知简单的php性能优化注意点
2016/01/04 PHP
php中二分法查找算法实例分析
2016/09/22 PHP
PHP网站自动化配置的实现方法(必看)
2017/05/27 PHP
php实现微信模板消息推送
2018/03/30 PHP
php实现根据身份证获取精准年龄
2020/02/26 PHP
Laravel 修改验证异常的响应格式实例代码详解
2020/05/25 PHP
js DataSet数据源处理代码
2010/03/29 Javascript
jQuery简单实现网页选项卡特效
2014/11/24 Javascript
kindeditor修复会替换script内容的问题
2015/04/03 Javascript
Node.js Express 框架 POST方法详解
2017/01/23 Javascript
原生javascript上传图片带进度条【实例分享】
2017/04/06 Javascript
Javascript实现信息滚动效果
2017/05/18 Javascript
vue axios 二次封装的示例代码
2017/12/08 Javascript
anime.js 实现带有描边动画效果的复选框(推荐)
2017/12/24 Javascript
Vue组件开发技巧总结
2018/03/04 Javascript
vue中的$emit 与$on父子组件与兄弟组件的之间通信方式
2018/05/13 Javascript
小程序测试后台服务的方法(ngrok)
2019/03/08 Javascript
jquery将json转为数据字典的实例代码
2019/10/11 jQuery
浅谈layui 绑定form submit提交表单的注意事项
2019/10/25 Javascript
vuex入门最详细整理
2020/03/04 Javascript
Python FTP操作类代码分享
2014/05/13 Python
Python打包可执行文件的方法详解
2016/09/19 Python
Python爬取数据并写入MySQL数据库的实例
2018/06/21 Python
python3实现名片管理系统
2020/11/29 Python
Python3环境安装Scrapy爬虫框架过程及常见错误
2019/07/12 Python
Django框架自定义模型管理器与元选项用法分析
2019/07/22 Python
python3 使用traceback定位异常实例
2020/03/09 Python
Python面试题:Python里面如何生成随机数
2015/03/12 面试题
中学生检讨书范文
2014/11/03 职场文书
2014年乡镇纪委工作总结
2014/12/19 职场文书
道德与公民自我评价
2015/03/09 职场文书
MySQL之PXC集群搭建的方法步骤
2021/05/25 MySQL