热搜:NVER node 开发 php

php并发抓图怎么知道有没抓完呢

2024-09-13 14:00:01
php并发抓图怎么知道有没抓完呢

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


回复讨论(解决方案)

抓回来了才会写盘
你在程序中维护一个目标列表,当列表中的文件都存在了,就可以打包了

多线程同步问题,信号量同步。

怎么抓图的,能否分享

多线程同步问题,信号量同步。

这位仁兄,可否解释更清楚一点呢。

抓回来了才会写盘
你在程序中维护一个目标列表,当列表中的文件都存在了,就可以打包了

版主 这个方法我想过。觉得挺麻烦的。因为我这边有几百个专题进行循环,一个专题内容有七八张图片。
每次通过正则获取内容中的图片地址,抓取到服务器;再压图大小。

如果需要记录,那应该是一次循环并发多个进程。然后执行完了再进入下个循环。

怎么抓图的,能否分享

抓图不难   
最简单的就是file_get_contents

你难道不记录哪个图片是哪个专题的吗?

你难道不记录哪个图片是哪个专题的吗?

没有关联图片记录表
因为内容可能经常要更新,目前增加无太大的意义。

为每一个专题建立一个文件夹,每次用正则匹配的时候,就统计一下有几张图片,然后把这个数据写入到文件夹下的一个专用文件中,如.number等!

另写一个打包程序,不停的扫描这些文件夹下的文件,并与特殊文件中的文件个数进行比较,如果文件个数相等就直接打包,并删除文件夹!

PV操作。。你要维持一个信号量。简单的说是一个变量。如果程序运行之前你就知道要抓取多少文件,那么这个值在一开始就是确定的,比如说你知道要抓取5张图片,那么这个变量的值就是5,每个子进程完成一张图片抓取动作这个变量就减一,最终为0时表示全抓完了。

如果一开始不知道要抓多少图片,那么这个信号量需要动态维护了,且要加入其他信号量来控制进程间的同步。比如有可能该信号量为0,但实际上还有进程在分析是否还有图片要进行抓取,而因为该信号量为0,程序直接退出。这样的情况也要考虑。

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

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

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

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

为每一个专题建立一个文件夹,每次用正则匹配的时候,就统计一下有几张图片,然后把这个数据写入到文件夹下的一个专用文件中,如.number等!

另写一个打包程序,不停的扫描这些文件夹下的文件,并与特殊文件中的文件个数进行比较,如果文件个数相等就直接打包,并删除文件夹!

这个方法挺好的。不过可能用表会更好点,因为可以记更多东西。比如已触发抓取的图片,抓取的状态;完成的时间等。

我简单描述下这边的情况
由于软件那边的一个专题app,有这样一个功能。
用户需要可以下载离线包浏览专题。

和软件那边约定好的格式为zip 

zip内结构为   
文件夹(专题id)对应多个专题图片  一个专题首页
而多个专题就会生成多个文件夹,文件夹名为专题id。

我现在的工作是要将这些专题生成文件夹数据,然后再打包为zip。提供给软件那边下载。
专题图片是由专题内容中正则匹配图片地址,再抓回来的。
现在出现的问题,由于几百个专题。一个专题内容有八九张图片;
造成抓取速度狠慢。

或者我需要一个表,记录每次循环正则匹配的图片数;每次抓取成功或失败都去减少这个量。
然后在程序中while查询这个数量,直到为零的时候就进入下一个专题。

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

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

抓取宜使用 curl,技术简单且效率高
curl 可直接将抓取的数据写入文件
curl_multi 可同时挂载多个 curl
curl_getinfo 可获取相关的工作信息(如果需要的话)

判定 curl_multi 各成员结束,就判定了抓取结束
这也符合你不打算保存进度信息的初衷

抓取宜使用 curl,技术简单且效率高
curl 可直接将抓取的数据写入文件
curl_multi 可同时挂载多个 curl
curl_getinfo 可获取相关的工作信息(如果需要的话)

判定 curl_multi 各成员结束,就判定了抓取结束
这也符合你不打算保存进度信息的初衷

版主  我可以加多个表记录状态,不过这个表应该怎样设计好呢。
一个包关联多个专题,多个包可以并发进行生成zip操作。
我想过这样的表结构
  
proc的结构
id  图片地址  包id  执行状态(1为已抓取) 专题id 

一开始清空 proc 当前生成 包id的记录数
循环专题的时候 
匹配了图片地址    一张为一条记录插入这张表。
抓取成功或失败则更新执行的状态
最后有个循环   
直到查询这张表的某个包,某个专题的图片执行状态为1的记录数等于正则匹配的图片数则进入下一个专题循环。

我不确定有没描述清楚,这个生成过程还有其它的一些操作;刚开始我只抽了关键的一些来描述。

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

版主大哥  我在等你回复呢

我已经按这个想法写好程序   下午测试

你测试了,发现不足就改进
发现不能解决的问题就提问

修正了一下午   用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比这个更快。

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 - 获取所有相关的插座与卷曲的扩展名,这样就可以“选择”

今天研究一下,用这个方式的话。应该就不用表老记录图片数量啦。

表来记录图片数量啦

搞明白啦  谢谢大家。结贴 !