想用PHP的CURL採集蝦米網的音樂資訊。
但是很慢,採集到50個左右的時候就會停掉,然後網頁卡住,第二次啟動並執行時候就無法採集,應該是根據IP識別後,不允許採集了吧,所以基本上採集資料非常慢。
請問這種大資料的採集應該怎麼做?
也有可能是我代碼的問題。
以下是部分代碼。
$j=0;//起始ID$id = 200000;//採集1000條//儲存採集的資料$data = array();while($j<1000){$url = 'http://www.xiami.com/song/'.($id++);$ch = curl_init();$status = curl_getinfo($ch);///$status['redirect_url'] ;// 跳轉到的新地址$header[]='Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8';$header[]='Accept-Encoding:gzip,deflate,sdch';$header[]='Accept-Language:zh-CN,zh;q=0.8';$header[]='Cache-Control:max-age=0';$header[]='Connection:keep-alive';$header[]='Cookie:_unsign_token=a35437bd35c221c09a0e6f564e17c225; __gads=ID=7fcc242f6fd63d77:T=1408774454:S=ALNI_Mae8MH6vL5z6q4NlGYzyqgD4jHeEg; bdshare_firstime=1408774454639; _xiamitoken=3541aab48832ba3ceb089de7f39b9b0f; pnm_cku822=211n%2BqZ9mgNqgJnCG0Zu8%2BzyLTPuc%2B7wbrff98%3D%7CnOiH84T3jPCG%2FIr%2BiPOG8lI%3D%7CneiHGXz6UeRW5k4rRCFXIkcoTdd7ym3fZdO2FrY%3D%7Cmu6b9JHlkuGa5pDqnOie5ZDkmeqb4ZTule6V7ZjjlOib7JrmkvdX%7Cm%2B%2BT%2FGIUew96DXsUYBd4HawbrTOXOVI4iyOLIYUqT%2B9P%7CmO6BH2wDcB9rHGsYdwRrH2gfbAN%2FDH8QZBNkF3gDeQqqCg%3D%3D%7Cme6d7oHyneiH84Twn%2BmR64TzUw%3D%3D; CNZZDATA921634=cnzz_eid%3D1437506062-1408774274-%26ntime%3D1408937320; CNZZDATA2629111=cnzz_eid%3D2021816723-1408774274-%26ntime%3D1408937320; isg=075E6FBDF77039CEB63A1BA239420244';$header[]='Host:www.xiami.com';$header[]='User-Agent:Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1653.0 Safari/537.36';curl_setopt($ch, CURLOPT_URL, $url);//要訪問的地址curl_setopt($ch, CURLOPT_HTTPHEADER, $header);//設定http頭curl_setopt($ch, CURLOPT_HEADER, 0);//顯示返回的Header地區內容curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);//擷取的資訊以檔案流的形式返回curl_setopt($ch, CURLOPT_TIMEOUT, 20);//設定逾時限制防止死迴圈$content = curl_exec($ch);//執行操作$curl_errno = curl_errno($ch);$curl_error = curl_error($ch);curl_close($ch);//關閉CURL會話preg_match('/name="description"\s+content="《(.+)》演唱者(.+),所屬專輯《(.+)》/', $content,$matches);//如果歌曲名字為空白,跳過if(empty($matches[1]) || trim($matches[1]) == ''){continue;}//匹配出的資料$data[$id]['song'] = empty($matches[1])?' ':$matches[1];$data[$id]['songer'] = empty($matches[2])?' ':$matches[2];$data[$id]['album'] = empty($matches[3])?' ':$matches[3];preg_match('/album\/(\d+)/', $content,$matches);$data[$id]['albumId'] = empty($matches[1])?0:$matches[1];preg_match('/\/artist\/(\d+)/', $content,$matches);$data[$id]['songerId'] = empty($matches[1])?0:$matches[1];//歌詞preg_match('/(.*)<\/div>/Us', $content,$matches);$data[$id]['lrc'] = empty($matches[1])?' ':addslashes($matches[1]);//分享 分享(3269)preg_match('/分享\((\d+)\)<\/em>/Us', $content,$matches);$data[$id]['share'] = empty($matches[1]) ? 0:$matches[1];//評論次數 920preg_match('/
(\d+)<\/span>/Us', $content,$matches);$data[$id]['comment_count'] = empty($matches[1])?0:$matches[1];//入庫操作//print_r($data);//_____________________________$j++;usleep(3000);}
回複討論(解決方案)
親,用snoopy類吧
親用 Ruby 或者 Go 吧
開玩笑,就算你要跑好歹你也弄成命令列的模式跑呀....
應該是xiami.com伺服器有限制,禁止採集吧
1,每個url請求只採10-20打,然後做個跳轉在繼續採集,這樣也可以防止頁面逾時,如果你在虛機上運行,長時間點用cpu,進程可能會被kill.
2,每次url請求header中的user-agent,cookies,最好都能改一下。
3,如果還不行,用火車頭試試吧!
4,如果火車也不行,那就放棄這個站吧!
把foreach拆分成迴圈執行同一頁面。
第一次瀏覽器或者cronrab定時執行 http://localhost/caiji.php?num=1 每次完成後,$_GET['num']+1;curl 重複l執行同一指令碼,當$_GET['num']==1000後,退出,不再執行curl。
if($_GET['num']){$url = 'http://www.xiami.com/song/'.$_GET['num'];//你的代碼$_GET['num'])++;}if($_GET['num']<1001){ $ch = curl_init();curl_setopt($ch, CURLOPT_URL,"http://localhost/caiji.php?num=".$_GET['num']));curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);curl_setopt($ch, CURLOPT_CONNECTTIMEOUT ,2); curl_setopt($ch, CURLOPT_TIMEOUT ,2);curl_exec($ch);curl_close($ch);}else{ exit;}