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);这段和上面的重复
你用了 curl_multi_select 函数,却又不知道他是干什么的,....手册说 curl_multi_select -- Get all the sockets associated with the cURL extension, which can then be "selected" google说 curl_multi_select - 获取所有相关的插座与卷曲的扩展名,这样就可以“选择”
抓图不难
最简单的就是file_get_contents
也可是用iframe实现吧
php 5.+ 之后的curl是支持多线程的,你是每下载一个就要打包一次?
由于软件那边的一个专题app,有这样一个功能。
用户需要可以下载离线包浏览专题。和软件那边约定好的格式为zip zip内结构为
文件夹(专题id)对应多个专题图片 一个专题首页
而多个专题就会生成多个文件夹,文件夹名为专题id。我现在的工作是要将这些专题生成文件夹数据,然后再打包为zip。提供给软件那边下载。
专题图片是由专题内容中正则匹配图片地址,再抓回来的。
现在出现的问题,由于几百个专题。一个专题内容有八九张图片;
造成抓取速度狠慢。或者我需要一个表,记录每次循环正则匹配的图片数;每次抓取成功或失败都去减少这个量。
然后在程序中while查询这个数量,直到为零的时候就进入下一个专题。
有办法的 可以用fsockopen触发抓图程序的链接。 不需等待该链接返回,程序会继续跑。
curl 可直接将抓取的数据写入文件
curl_multi 可同时挂载多个 curl
curl_getinfo 可获取相关的工作信息(如果需要的话)判定 curl_multi 各成员结束,就判定了抓取结束
这也符合你不打算保存进度信息的初衷
版主 我可以加多个表记录状态,不过这个表应该怎样设计好呢。
一个包关联多个专题,多个包可以并发进行生成zip操作。
我想过这样的表结构
proc的结构
id 图片地址 包id 执行状态(1为已抓取) 专题id 一开始清空 proc 当前生成 包id的记录数
循环专题的时候
匹配了图片地址 一张为一条记录插入这张表。
抓取成功或失败则更新执行的状态
最后有个循环
直到查询这张表的某个包,某个专题的图片执行状态为1的记录数等于正则匹配的图片数则进入下一个专题循环。我不确定有没描述清楚,这个生成过程还有其它的一些操作;刚开始我只抽了关键的一些来描述。
* 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比这个更快。
//当无数据时或请求暂停时,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);这段和上面的重复
curl_multi_select -- Get all the sockets associated with the cURL extension, which can then be "selected"
google说
curl_multi_select - 获取所有相关的插座与卷曲的扩展名,这样就可以“选择”