php多线程抓取多个网页(phpcurl_exec()并发抓取网页内容_multi())

优采云 发布时间: 2021-12-01 16:06

  php多线程抓取多个网页(phpcurl_exec()并发抓取网页内容_multi())

  php curl_multi_exec() 并发抓取网页内容

  php是单线程语言,所以在某些方面速度不如java,java是多线程语言。毕竟主要方面不在这里。。不过php也有自己的多线程(实际上是并发)方法——curl_multi_exec()。

  我们可以使用curl来获取网页的内容(如果你不懂curl,可以找个简单的例子看看),但是如果同时获取多个网页的内容,速度是不理想。这时候 curl_multi_exec() 就可以发挥作用了。

  以下是我爬取优酷内容的例子:

  

function async_get_url($url_array, $wait_usec = 0)

{

if (!is_array($url_array))

return false;

$wait_usec = intval($wait_usec);

$data = array();

$handle = array();

$running = 0;

$mh = curl_multi_init(); // multi curl handler

$i = 0;

foreach($url_array as $url) {

$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, $url);

curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // return don't print

curl_setopt($ch, CURLOPT_TIMEOUT, 30);

curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)');

curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); // 302 redirect

curl_setopt($ch, CURLOPT_MAXREDIRS, 7);

curl_multi_add_handle($mh, $ch); // 把 curl resource 放進 multi curl handler 裡

$handle[$i++] = $ch;

}

/* 此做法就可以避免掉 CPU loading 100% 的問題 */

// 參考自: http://www.hengss.com/xueyuan/sort0362/php/info-36963.html

do {

$mrc = curl_multi_exec($mh, $active);

} while ($mrc == CURLM_CALL_MULTI_PERFORM);

while ($active and $mrc == CURLM_OK) {

if (curl_multi_select($mh) != -1) {

do {

$mrc = curl_multi_exec($mh, $active);

} while ($mrc == CURLM_CALL_MULTI_PERFORM);

}

}

/*

// 感謝 Ren 指點的作法. (需要在測試一下)

// curl_multi_exec的返回值是用來返回多線程處裡時的錯誤,正常來說返回值是0,也就是說只用$mrc捕捉返回值當成判斷式的迴圈只會運行一次,而真的發生錯誤時,有拿$mrc判斷的都會變死迴圈。

// 而curl_multi_select的功能是curl發送請求後,在有回應前會一直處於等待狀態,所以不需要把它導入空迴圈,它就像是會自己做判斷&自己決定等待時間的sleep()。

/* 讀取資料 */

foreach($handle as $i => $ch) {

$content = curl_multi_getcontent($ch);

$data[$i] = (curl_errno($ch) == 0) ? $content : false;

}

/* 移除 handle*/

foreach($handle as $ch) {

curl_multi_remove_handle($mh, $ch);

}

curl_multi_close($mh);

return $data;

}

$url="http://m.youku.com/wap/";

$reg1="/(.*?)/i";//获取视频链接

$reg2="/]*)\s*class=\"imgdetail\"\s*src=('|\")([^'\"]+)('|\")/i";

$reg3="";

$reg4= "/.*?/i";//获取视频标题(备选)

// 创建两个cURL资源

$ch1 = curl_init();

$resultArray=array();//装载所有数据的数组

$ch=array();

//$ch2 = curl_init();

// 指定URL和适当的参数

curl_setopt($ch1, CURLOPT_URL,$url);

curl_setopt($ch1, CURLOPT_RETURNTRANSFER, 1);

curl_setopt($ch1, CURLOPT_HEADER, 0);

$content=curl_exec($ch1);

curl_close($ch1);

//$content=file_get_contents($url);

preg_match_all($reg1, $content,$matches);

$video=$matches[0];//首页视频的链接

//print_r($video);

foreach ($video as $a=>$key)

{

$position=strpos($key, "href");

$substring=substr($key, $position+11);

$pos=strpos($substring, ">");

$link=substr($substring, 0,$pos-1);

$nextUrl[$a]=$url.$link;

}

//$url_array = array(

// 'http://www.google.com',

// 'http://www.baidu.com',

//);

//print_r($nextUrl);

//print_r(async_get_url($nextUrl));

//并发获取所有网页的内容

$allData=async_get_url($nextUrl);

foreach ($allData as $page)

{

//获取视频图片

preg_match_all($reg2, $page,$img);

$img_arr=$img[0];

foreach ($img_arr as $arr)

{

$position=strpos($arr, "src");

$sub=substr($arr, $position+5);

$pos=strpos($sub, "\"");

$last=substr($sub, 0,$pos);

}

//获取视频高清点播地址

preg_match_all($reg3, $page,$vids);

$video_arr=$vids[0];

$vid=$video_arr[0];

$position=strpos($vid, "href");

$v_string=substr($vid, $position+11);

$pos=strpos($v_string, "\"");

$add=substr($v_string, 0,$pos);

$video_url=$url.$add;

//获取视频的标题

preg_match_all($reg4, $page,$match);

$title=$match[0];

//print_r($er);

$r=serialize($title);

$position=mb_strpos($r, "");

$sub=substr($r, 0,$position);

$pos=mb_strrpos($sub, ">");

$til=substr($sub, $pos+1);

//整合到一个数组

$subArray=array('image'=>$last,'video'=>$video_url,'title'=>$til);

array_push($resultArray, $subArray);

}

echo json_encode($resultArray);</p>

  重点是函数async_get_url

  

do {

$mrc = curl_multi_exec($mh, $active);

} while ($mrc == CURLM_CALL_MULTI_PERFORM);

while ($active and $mrc == CURLM_OK) {

if (curl_multi_select($mh) != -1) {

do {

$mrc = curl_multi_exec($mh, $active);

} while ($mrc == CURLM_CALL_MULTI_PERFORM);

}

}

  上一段是重点和难点。

<p>第一个循环,$mrc == CURLM_CALL_MULTI_PERFORM(-1)表示还有句柄资源没有处理,所以继续$mrc = curl_multi_exec($mh, $active)

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线