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 相关文章推荐
输出控制类
Oct 09 PHP
使用 MySQL 开始 PHP 会话
Dec 21 PHP
php下通过POST还是GET来传值
Jun 05 PHP
PHP 文件类型判断代码
Mar 13 PHP
同台服务器使用缓存APC效率高于Memcached的演示代码
Feb 16 PHP
php入门之连接mysql数据库的一个类
Apr 21 PHP
深入file_get_contents与curl函数的详解
Jun 25 PHP
3款值得推荐的微信开发开源框架
Oct 28 PHP
解决phpcms更换javascript的幻灯片代码调用图片问题
Dec 26 PHP
PHP实现返回JSON和XML的类分享
Jan 28 PHP
PHP实现获取url地址中顶级域名的方法示例
Jun 05 PHP
PHP之多条件混合筛选功能的实现方法
Oct 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
一个颜色轮换的简单例子
2006/10/09 PHP
php 301转向实现代码
2008/09/18 PHP
基于OpenCV的PHP图像人脸识别技术
2009/10/11 PHP
确保Laravel网站不会被嵌入到其他站点中的方法
2019/10/18 PHP
二级域名转向类
2006/11/09 Javascript
js玩一玩WSH吧
2007/02/23 Javascript
一个tab标签切换效果代码
2009/03/27 Javascript
firefox浏览器不支持innerText的解决方法
2013/08/07 Javascript
基于jquery的网站幻灯片切换效果焦点图代码
2013/09/15 Javascript
JavaScript调试技巧之console.log()详解
2014/03/19 Javascript
jquery下拉select控件操作方法分享(jquery操作select)
2014/03/25 Javascript
js隐式全局变量造成的bug示例代码
2014/04/22 Javascript
JavaScript获取伪元素(Pseudo-Element)属性的方法技巧
2015/03/13 Javascript
js实现简易的单数字随机抽奖(0-9)
2020/03/19 Javascript
jQuery地图map悬停显示省市代码分享
2015/08/20 Javascript
详解用vue编写弹出框组件
2017/07/04 Javascript
jQuery插件artDialog.js使用与关闭方法示例
2017/10/09 jQuery
vue中$refs的用法及作用详解
2018/04/24 Javascript
vue 点击其他区域关闭自定义div操作
2020/07/17 Javascript
python字典多条件排序方法实例
2014/06/30 Python
python超简单解决约瑟夫环问题
2015/05/12 Python
分享Python文本生成二维码实例
2016/01/06 Python
Python数组定义方法
2016/04/13 Python
Python 对象中的数据类型
2017/05/13 Python
Python3使用SMTP发送带附件邮件
2020/06/16 Python
浅谈Pandas:Series和DataFrame间的算术元素
2018/12/22 Python
python 实现让字典的value 成为列表
2019/12/16 Python
在pytorch中实现只让指定变量向后传播梯度
2020/02/29 Python
Python3中FuzzyWuzzy库实例用法
2020/11/18 Python
Python实现图片指定位置加图片水印(附Pyinstaller打包exe)
2021/03/04 Python
ASOS比利时:英国线上零售商及自有品牌
2018/07/29 全球购物
Linux中如何用命令创建目录
2015/01/12 面试题
酒店中秋节活动方案
2014/01/31 职场文书
空气的环保标语
2014/06/12 职场文书
商品陈列协议书
2014/09/29 职场文书
辩论赛新闻稿
2015/07/17 职场文书