您好,登錄后才能下訂單哦!
待下載的網頁地址放在$urls數組中,按指定的并發數多進程下載網頁,下載的網頁保存在本地硬盤,下載的網頁大小通過linux消息隊列發送給父進程累加,全部網頁下載完成后,父進程顯示下載的網頁數、字節數。代碼如下。
<? //$urls數組用于保存要下載的網址,實際應用中一般從文件或數據庫中讀取網址保存到$urls中。 $urls = array('http://www.qq.com','http://www.sohu.com','http://www.sina.com.cn',....); $urls_num = count($urls);//數組大小,也是網址數量 $msg_file = "/tmp/download_msgqueue.txt";//下面3行創建linux消息隊列下,該文件須先創建好 $msg_queuekey = ftok($msg_file,'R');//touch /tmp/download_msgqueue.txt $msg_queue = msg_get_queue($msg_queuekey, 0666); $maxtasknum = 5;//設定并發進程數 $ct = 0;//$urls數組用的計數器 $cttask = 0;//并發進程計數器 $pids = array();//保存進程的數組 $total_bytes = 0;//下載網頁的字節數 while ($ct<$urls_num) {//循環抓取$urls數組中指定的網頁 while ($cttask<$maxtasknum && $ctproc<$urls_num) {//fork出指定的并發數進程 $pids[$ct] = pcntl_fork(); if ($pids[$ct]==-1) { echo "create subproc fail.\n"; exit(0); } elseif ($pids[$ct]>0) {//父進程 } elseif ($pids[$ct]==0) {//子進程 download($urls[$ct], $msg_queue); exit(0); } $cttask++; $ct++; } $tmppid = pcntl_waitpid(0, $status);//等待子進程結束 foreach($pids as $key => $pid) { if($tmppid == $pid){ unset($pids[$key]); $cttask--;//子進程結束后,并發進程計數器減1 } } do {//從消息隊列出取出每個網頁的大小,計算下載的字節數。如果要下載的網頁很多,需要把此段代碼放到下載網頁的循環中,否則可能會出現隊列滿的情況。 msg_receive($msg_queue, 0, $message_type, 16, $message, true, MSG_IPC_NOWAIT); //echo "[".$message."]\n"; $total_bytes += $message; $a = msg_stat_queue($msg_queue); if($a['msg_qnum'] == 0){//這種方式退出比$ct==$urls_num好,因為如果fork==-1,就不會有$urls_num個消息,程序會永遠等待消息。 break; } } while(true); } while ($cttask > 0) {//等待最后$cttask個子進程結束 $tmppid = pcntl_waitpid(0,$status); foreach($pids as $key => $pid) { if($tmppid == $pid){ unset($pids[$key]); $cttask--; } } } do {//取得最后$cttask個子進程的消息 msg_receive($msg_queue, 0, $message_type, 16, $message, true, MSG_IPC_NOWAIT); //echo "[".$message."]\n"; $total_bytes += $message; $a = msg_stat_queue($msg_queue); if($a['msg_qnum'] == 0){ break; } } while(true); msg_remove_queue($msg_queue);//刪除消息隊列 echo "\nDone. download: ".$urls_num." pages,total: ".round($total_bytes/1024,3)." KB \n"; exit(0); function download($url, $msg_queue) {//下載指定網頁,把內容保存在本地硬盤,并下載內容的長度放入消息隊列中 $dirname = "/tmp/donwload/";//保存下載網頁的目錄,要事先創建好 $content = file_get_contents($url); if ($content === false) { $content = 0; } $url_parts = parse_url($url); $fname = $dirname.$url_parts['host']; $ret = file_put_contents($fname, $content); msg_send($msg_queue, 1, strlen($content)); } ?>
參考資料:
PHP實現進程間通信:消息隊列 https://www.douban.com/note/245520545/
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。