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 相关文章推荐
php中目录,文件操作详谈
Mar 19 PHP
php下封装较好的数字分页方法
Nov 23 PHP
深入理解require与require_once与include以及include_once的区别
Jun 05 PHP
PHP垃圾回收机制引用计数器概念分析
Jun 24 PHP
解析php多线程下载远程多个文件
Jun 25 PHP
php调整gif动画图片尺寸示例代码分享
Dec 05 PHP
6个超实用的PHP代码片段
Aug 10 PHP
php实现XML和数组的相互转化功能示例
Feb 08 PHP
PHP 实现浏览记录并按日期分组
May 11 PHP
phpcms配置列表页以及获得文章发布时间
Jul 04 PHP
详解php 使用Callable Closure强制指定回调类型
Oct 26 PHP
PHP中PCRE正则解析代码详解
Apr 26 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
PHP魔术引号所带来的安全问题分析
2014/07/15 PHP
PHP实现图片裁剪、添加水印效果代码
2014/10/01 PHP
php中的常用魔术方法汇总
2016/02/14 PHP
php基于Fleaphp框架实现cvs数据导入MySQL的方法
2016/02/23 PHP
PHP设计模式之注册树模式分析
2018/01/26 PHP
PHP如何通过date() 函数格式化显示时间
2020/11/13 PHP
JS 图片缩放效果代码
2010/06/09 Javascript
JavaScript使用过程中需要注意的地方和一些基本语法
2010/08/26 Javascript
jquery.validate分组验证代码
2011/03/17 Javascript
Javascript实现页面跳转的几种方式分享
2013/10/26 Javascript
JS实现距离上次刷新已过多少秒示例
2014/05/23 Javascript
JavaScript编程中的Promise使用大全
2015/07/28 Javascript
基于JavaScript将表单序列化类型的数据转化成对象的处理(允许对象中包含对象)
2015/12/28 Javascript
总结javascript中的六种迭代器
2016/08/16 Javascript
JS实现图片上传预览功能
2016/11/21 Javascript
JavaScript获取tr td 的三种方式全面总结(推荐)
2017/08/15 Javascript
Javascript网页抢红包外挂实现分享
2018/01/11 Javascript
对layui数据表格动态cols(字段)动态变化详解
2019/10/25 Javascript
JQuery事件冒泡和默认行为代码实例
2020/05/13 jQuery
vue移动端下拉刷新和上滑加载
2020/10/27 Javascript
Vite和Vue CLI的优劣
2021/01/30 Vue.js
在RedHat系Linux上部署Python的Celery框架的教程
2015/04/07 Python
解决python3 urllib中urlopen报错的问题
2017/03/25 Python
Python调用C++,通过Pybind11制作Python接口
2018/10/16 Python
对Python定时任务的启动和停止方法详解
2019/02/19 Python
Pytorch实现的手写数字mnist识别功能完整示例
2019/12/13 Python
重写django的model下的objects模型管理器方式
2020/05/15 Python
解决Pycharm 中遇到Unresolved reference 'sklearn'的问题
2020/07/13 Python
Python函数__new__及__init__作用及区别解析
2020/08/31 Python
完美解决Pycharm中matplotlib画图中文乱码问题
2021/01/11 Python
英国天然抗衰老护肤品品牌:Nakin Skin Care
2019/04/16 全球购物
经济管理毕业生求职信
2014/03/15 职场文书
初二学生评语大全
2014/12/26 职场文书
学校食堂食品安全承诺书
2015/04/29 职场文书
Go语言-为什么返回值为接口类型,却返回结构体
2021/04/24 Golang
DBCA命令行搭建Oracle ADG的流程
2021/06/11 Oracle