我有個程式,將圖片抓回來;然後打包成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=trueif (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 - 擷取所有相關的插座與捲曲的副檔名,這樣就可以“選擇”
今天研究一下,用這個方式的話。應該就不用表老記錄圖片數量啦。
表來記錄圖片數量啦
搞明白啦 謝謝大家。結貼 !