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生成带有雪花背景的验证码
Oct 09 PHP
PHP编程中八种常见的文件操作方式
Nov 19 PHP
php 连接mssql数据库 初学php笔记
Mar 01 PHP
php学习笔记 面向对象的构造与析构方法
Jun 13 PHP
php中生成随机密码的自定义函数代码
Oct 21 PHP
thinkphp视图模型查询提示ERR: 1146:Table 'db.pr_order_view' doesn't exist的解决方法
Oct 30 PHP
PHP+Mysql+jQuery中国地图区域数据统计实例讲解
Oct 10 PHP
PHP快速生成各种信息提示框的方法
Feb 03 PHP
Laravel 中使用 Vue.js 实现基于 Ajax 的表单提交错误验证操作
Jun 30 PHP
php从数据库中获取数据用ajax传送到前台的方法
Aug 20 PHP
PHP 并发场景的几种解决方案
Jun 14 PHP
微信公众号之主动给用户发送消息功能
Jun 22 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
全国FM电台频率大全 - 29 青海省
2020/03/11 无线电
真正的ZIP文件操作类(php)
2007/07/21 PHP
Ha0k 0.3 PHP 网页木马修改版
2009/10/11 PHP
laravel安装zend opcache加速器教程
2015/03/02 PHP
PHP二分查找算法示例【递归与非递归方法】
2016/09/29 PHP
php实现留言板功能(会话控制)
2017/05/23 PHP
javascript 支持ie和firefox杰奇翻页函数
2008/07/22 Javascript
ajax 缓存 问题 requestheader
2010/08/01 Javascript
jquery不会自动回收xmlHttpRequest对象 导致了内存溢出
2012/06/18 Javascript
jquery实现图片预加载
2015/12/25 Javascript
js时间比较 js计算时间差的简单实现方法
2016/08/26 Javascript
JavaScript中Array的实用操作技巧分享
2016/09/11 Javascript
JavaScript 字符串常用操作小结(非常实用)
2016/11/30 Javascript
Vue脚手架的简单使用实例
2018/07/10 Javascript
koa2 数据api中间件设计模型的实现方法
2020/07/13 Javascript
利用Python脚本在Nginx和uwsgi上部署MoinMoin的教程
2015/05/05 Python
Python中的命令行参数解析工具之docopt详解
2017/03/27 Python
python实现快速排序的示例(二分法思想)
2018/03/12 Python
对numpy中的transpose和swapaxes函数详解
2018/08/02 Python
python微信公众号之关注公众号自动回复
2018/10/25 Python
Python动态语言与鸭子类型详解
2019/07/01 Python
基于python纯函数实现井字棋游戏
2020/05/27 Python
Html5 页面适配iPhoneX(就是那么简单)
2019/09/05 HTML / CSS
全球领先美式家具品牌:Ashley爱室丽家居
2017/08/07 全球购物
应届生服装设计自我评价
2013/09/20 职场文书
求职自荐信范文格式
2013/11/29 职场文书
简单的项目建议书模板
2014/03/12 职场文书
2014年居委会工作总结
2014/12/09 职场文书
检讨书怎么写
2015/01/23 职场文书
会计工作岗位职责
2015/02/03 职场文书
2015年度党员个人总结
2015/02/14 职场文书
入党积极分子个人总结
2015/03/02 职场文书
法制工作总结2015
2015/07/23 职场文书
导游词之平津战役纪念馆
2019/11/04 职场文书
利用js实现简单开关灯代码
2021/11/23 Javascript
JAVA SpringMVC实现自定义拦截器
2022/03/16 Python