我有个程序,将图片抓回来;然后打包成zip。
当前用的是单线程,由于实在太慢。所以想用多线程并发抓。
但这样做的话,我不知道什么时候可以打包zip。
大侠们给点建议吧 

解决方案 »

  1.   


    抓图不难   
    最简单的就是file_get_contents
      

  2.   

    为每一个专题建立一个文件夹,每次用正则匹配的时候,就统计一下有几张图片,然后把这个数据写入到文件夹下的一个专用文件中,如.number等!另写一个打包程序,不停的扫描这些文件夹下的文件,并与特殊文件中的文件个数进行比较,如果文件个数相等就直接打包,并删除文件夹!
      

  3.   

    另外,你怎么用的多线程?PHP不支持多线程的。
      

  4.   

    apache有多线程组件
    也可是用iframe实现吧
      

  5.   


    php 5.+ 之后的curl是支持多线程的,你是每下载一个就要打包一次?
      

  6.   

    我简单描述下这边的情况
    由于软件那边的一个专题app,有这样一个功能。
    用户需要可以下载离线包浏览专题。和软件那边约定好的格式为zip zip内结构为   
    文件夹(专题id)对应多个专题图片  一个专题首页
    而多个专题就会生成多个文件夹,文件夹名为专题id。我现在的工作是要将这些专题生成文件夹数据,然后再打包为zip。提供给软件那边下载。
    专题图片是由专题内容中正则匹配图片地址,再抓回来的。
    现在出现的问题,由于几百个专题。一个专题内容有八九张图片;
    造成抓取速度狠慢。或者我需要一个表,记录每次循环正则匹配的图片数;每次抓取成功或失败都去减少这个量。
    然后在程序中while查询这个数量,直到为零的时候就进入下一个专题。
      

  7.   


    有办法的  可以用fsockopen触发抓图程序的链接。 不需等待该链接返回,程序会继续跑。
      

  8.   

    抓取宜使用 curl,技术简单且效率高
    curl 可直接将抓取的数据写入文件
    curl_multi 可同时挂载多个 curl
    curl_getinfo 可获取相关的工作信息(如果需要的话)判定 curl_multi 各成员结束,就判定了抓取结束
    这也符合你不打算保存进度信息的初衷
      

  9.   


    版主  我可以加多个表记录状态,不过这个表应该怎样设计好呢。
    一个包关联多个专题,多个包可以并发进行生成zip操作。
    我想过这样的表结构
      
    proc的结构
    id  图片地址  包id  执行状态(1为已抓取) 专题id 一开始清空 proc 当前生成 包id的记录数
    循环专题的时候 
    匹配了图片地址    一张为一条记录插入这张表。
    抓取成功或失败则更新执行的状态
    最后有个循环   
    直到查询这张表的某个包,某个专题的图片执行状态为1的记录数等于正则匹配的图片数则进入下一个专题循环。我不确定有没描述清楚,这个生成过程还有其它的一些操作;刚开始我只抽了关键的一些来描述。
      

  10.   

    版主  我proc表的设计合理不。
      

  11.   

    修正了一下午   用fsockopen 来触发一个抓取图片的脚本。如果不fgets就触发不了。本地试是可以的。搞不清楚什么原因。后来网上搜了个 ** 
     * curl 多线程 
     *  
     * @param array $array 并行网址 
     * @param int $timeout 超时时间
     * @return array 
     */ 
     function curl_http($array,$timeout){  $res = array();
      $mh = curl_multi_init();   //创建多个curl语柄
    $startime = getmicrotime();
      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定向级别
            curl_setopt($conn[$k], CURLOPT_HEADER, 0);    //这里不要header,加块效率
            curl_setopt($conn[$k], CURLOPT_FOLLOWLOCATION, 1); // 302 redirect
            curl_setopt($conn[$k],CURLOPT_RETURNTRANSFER,1);
            curl_multi_add_handle ($mh,$conn[$k]);  }
    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) {   curl_error($conn[$k]);
      //$res[$k]=curl_multi_getcontent($conn[$k]);//获得返回信息
      $header[$k] = curl_getinfo($conn[$k]);//返回头信息
      curl_close($conn[$k]);//关闭语柄
      curl_multi_remove_handle($mh, $conn[$k]);   //释放资源
      
    } curl_multi_close($mh);
    $endtime = getmicrotime();
    $diff_time = $endtime - $startime;

    return array( 'diff_time'=>$diff_time,
    'return'=>$res,
    'header'=>$header

    );
     
     }
     //计算当前时间
     function getmicrotime() {     list($usec, $sec) = explode(" ",microtime());
        return ((float)$usec + (float)$sec);
    }测试过还行。不过不知道为啥本地测试的话,file_get_contents比这个更快。
      

  12.   

    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);
            }
        }
    另外   不大理解这句的作用。 上面已经触发了链接。
    这段是用来检测什么时候完成的吗 ?            do {
                    $mrc = curl_multi_exec($mh, $active);
                } while ($mrc == CURLM_CALL_MULTI_PERFORM);这段和上面的重复
      

  13.   

    你用了 curl_multi_select 函数,却又不知道他是干什么的,....手册说
    curl_multi_select --  Get all the sockets associated with the cURL extension, which can then be "selected" 
    google说
    curl_multi_select - 获取所有相关的插座与卷曲的扩展名,这样就可以“选择”