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+XML 制作简单的留言本 图文教程
Nov 02 PHP
适用于抽奖程序、随机广告的PHP概率算法实例
Apr 09 PHP
codeigniter中测试通过的分页类示例
Apr 17 PHP
PHP实现模仿socket请求返回页面的方法
Nov 04 PHP
php结合正则获取字符串中数字
Jun 19 PHP
Laravel SQL语句记录方式(推荐)
May 26 PHP
支付宝支付开发――当面付条码支付和扫码支付实例
Nov 04 PHP
Zend Framework入门教程之Zend_Registry组件用法详解
Dec 09 PHP
基于PHP的加载类操作以及其他两种魔术方法的应用实例
Aug 28 PHP
php微信公众号开发之欢迎老朋友
Oct 20 PHP
laravel unique验证、确认密码confirmed验证以及密码修改验证的方法
Oct 16 PHP
TP - 比RBAC更好的权限认证方式(Auth类认证)
Mar 09 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
网页自动刷新,不产生嗒嗒声的一个解决方法
2007/03/27 Javascript
JS实现动态移动层及拖动浮层关闭的方法
2015/04/30 Javascript
javascript表单验证大全
2015/08/12 Javascript
angularjs在ng-repeat中使用ng-model遇到的问题
2016/01/21 Javascript
用原生JS对AJAX做简单封装的实例代码
2016/07/13 Javascript
jQuery 自定义下拉框(DropDown)附源码下载
2016/07/22 Javascript
浅谈toLowerCase和toLocaleLowerCase的区别
2016/08/15 Javascript
ES6记录异步函数的执行时间详解
2016/08/31 Javascript
利用VUE框架,实现列表分页功能示例代码
2017/01/12 Javascript
js canvas实现QQ拨打电话特效
2017/05/10 Javascript
关于webpack代码拆分的解析
2017/07/20 Javascript
select自定义小三角样式代码(实用总结)
2017/08/18 Javascript
Vue+axios实现统一接口管理的方法
2018/07/23 Javascript
Angular服务Request异步请求的实例讲解
2018/08/13 Javascript
three.js实现炫酷的全景3D重力感应
2018/12/30 Javascript
Echarts实现多条折线可拖拽效果
2019/12/19 Javascript
详解webpack的文件监听实现(热更新)
2020/09/11 Javascript
python连接mongodb操作数据示例(mongodb数据库配置类)
2013/12/31 Python
10种检测Python程序运行时间、CPU和内存占用的方法
2015/04/01 Python
Python语言的面相对象编程方式初步学习
2016/03/12 Python
Python 实现大整数乘法算法的示例代码
2019/09/17 Python
pyinstaller打包程序exe踩过的坑
2019/11/19 Python
Jupyter notebook命令和编辑模式常用快捷键汇总
2020/11/17 Python
使用CSS3制作响应式导航菜单的方法
2015/07/12 HTML / CSS
html5自动播放mov格式视频的实例代码
2020/01/14 HTML / CSS
为什么如下的代码int a=100,b=100;long int c=a * b;不能工作
2013/11/29 面试题
写一个函数返回1+2+3+…+n的值(假定结果不会超过长整型变量的范围)
2014/09/05 面试题
高中军训感想300字
2014/03/04 职场文书
小学开学标语
2014/07/01 职场文书
居委会个人对照检查材料思想汇报
2014/09/29 职场文书
个人年终总结开头
2015/03/06 职场文书
运动会加油稿
2015/07/22 职场文书
如何做好员工培训计划?
2019/07/09 职场文书
Redis官方可视化工具RedisInsight安装使用教程
2022/04/19 Redis
PYTHON基于Pyecharts绘制常见的直角坐标系图表
2022/04/28 Python
python和anaconda的区别
2022/05/06 Python