我這樣抓取百度地圖的數(shù)據(jù)

最近公司需要抓取百度地圖中所有藥店數(shù)據(jù),本人比較愚笨,斷斷續(xù)續(xù)花了2天時間才完成此次任務(wù)。期間遇到的各種小坑,但目前進(jìn)度良好。以下記錄的是我進(jìn)行任務(wù)的整個流程。

1、熟悉百度API,調(diào)用API獲得數(shù)據(jù)。

既然要拿百度地圖的數(shù)據(jù),那自然首選在地圖API入手。經(jīng)過了解,發(fā)現(xiàn)了 place api 可以使用。

Place API 提供區(qū)域檢索POI服務(wù)、POI詳情服務(wù)與團購信息檢索服務(wù)、商家團購詳情查詢。

區(qū)域檢索POI服務(wù)提供三種區(qū)域檢索方法:

城市內(nèi)檢索(對應(yīng)JavaScriptAPI的Search方法)

矩形檢索(對應(yīng)JavaScript API的SearchInBound方法)

圓形區(qū)域檢索(對應(yīng)JavaScript的SearchNearBy方法)。

調(diào)用此API也非常簡單,只需要用PHP生成一條URL,并生成get請求即可得到數(shù)據(jù)。由于API的每次調(diào)用默認(rèn)只返回10條信息,所以為了能夠獲得更多的信息,需要設(shè)置page_num參數(shù)進(jìn)行翻頁操作。這時候使用一個遞歸函數(shù)完成比較好。

class DataCollector{
public function getShopDataByCity($cityName,$keyword){
    $this->_getShopDataByCity($cityName,$keyword);
    return $this->shopData;
}
private function _getShopDataByCity($cityName,$keyword,$page_num=0){
    $url = "http://api.map.baidu.com/place/v2/search?q=$keyword&region=$cityName&output=json&ak=597a11f21bf9dfd3ab95632271b3832c&page_num=$page_num";
    $curl = new \Common\Lib\Curl();
    $result = $curl->get($url);
    $resultData = json_decode($result);

    if($resultData->results != null){
        foreach ($resultData->results as $value) {
            $value = $this->objectToArray($value);
            $this->shopData[] = $value;
        }
        //繼續(xù)尋找下一頁
        $this->_getShopDataByCity($cityName,$keyword,$page_num+1);
    }
    
}
}

運行一下,成功了返回數(shù)據(jù)。

2、發(fā)現(xiàn)數(shù)據(jù)不夠,并填坑

然而當(dāng)我換了幾個城市名調(diào)用的時候,發(fā)現(xiàn)API返回的數(shù)據(jù)最多是760條,這遠(yuǎn)遠(yuǎn)是不夠的。一個大城市的藥店總數(shù)能超過5000,而一些二線城市的藥店總數(shù)也能接近一千??磥戆俣仍贏PI上做了手腳,強行阻止了用戶扒她的數(shù)據(jù)。于是我繼續(xù)研究了她提供的API,發(fā)現(xiàn)給API支持矩形檢索。好,那就試試吧。

public function getShopDataByBounds($bounds,$keyword){
    $this->_getShopDataByBounds($bounds,$keyword);
    return $this->shopData;
}
private function _getShopDataByBounds(array $bounds,$keyword,$page_num=0){
    $url = "http://api.map.baidu.com/place/v2/search?query=$keyword&bounds=$bounds[0],$bounds[1],$bounds[2],$bounds[3]&output=json&ak=".DataCollector::AK."&page_num=$page_num";
    $result = $this->curl->get($url);
    $resultData = json_decode($result);
    $this->msg= $resultData->message;

    if($resultData->results != null){
        foreach ($resultData->results as $value) {
            $value = $this->objectToArray($value);
            $this->shopData[] = $value;
        }
        //繼續(xù)尋找下一頁
        $this->_getShopDataByBounds($bounds,$keyword,$page_num+1);
    }
}

好了,如果bounds的經(jīng)緯度間隔足夠小,就能夠拿到充足的數(shù)據(jù)。但是我們的大中國是由無數(shù)個小矩形組成的,這意味著獲得全部的數(shù)據(jù),就必須遍歷無數(shù)的矩形。但顯然沒什么好辦法,那就遍歷下去吧。

3、內(nèi)存溢出

我先使用上面的函數(shù)將中國這個大公雞的頭部拿下了,先用矩形框住公雞頭,在百度的拾取系統(tǒng)中找到矩形的左下角和右上角的大概的經(jīng)緯度,分別是:(26,95)(31,122.6)。使用下面的循環(huán)反復(fù)調(diào)用getShopDataByBounds()函數(shù),即可得到大公雞頭部的數(shù)據(jù)了。

for($i=26;$i<=31; $i = $i+0.1){
    for($j=95;$j<=122.6;$j=$j+0.1){
        $shopData = $cotor->getShopDataByBounds(array($i,$j,$i+0.1,$j+0.1),'藥店');
    }
}
print_r($shopData);

但是很不幸的是,程序運行了10分鐘左右,爆出了內(nèi)存溢出的錯誤,函數(shù)被意外終斷了。

4、解決問題

到底是怎么回事呢?其實重新審視一遍自己的代碼,很快就發(fā)現(xiàn)了問題,_getShopDataByBounds()函數(shù)使用到了class中的一個私有數(shù)組resultData。每次我調(diào)用_getShopDataByBounds()后,這個數(shù)組并沒有被重置,以至于它越來越大,到最后撐爆了內(nèi)存,爆出嚴(yán)重錯誤。因此,需要在調(diào)用外部函數(shù)getShopDataByBounds()的時候,必須先重置數(shù)組。

public function getShopDataByCity($cityName,$keyword){
    unset($this->shopData);
    unset($this->msg);
    $this->_getShopDataByCity($cityName,$keyword);
    return $this->shopData;
}

再次運行程序,OK了再也不出現(xiàn)內(nèi)存溢出情況了。

5、繼續(xù)調(diào)優(yōu)

程序安靜平穩(wěn)的運行了差不多兩個小時,這是突然發(fā)現(xiàn)后面再也不能獲取到數(shù)據(jù)了,而且在這兩個小時的時間里產(chǎn)生的數(shù)據(jù)只有1W多,效率太慢了。其實獲取不到數(shù)據(jù),是由于百度限制了每個AK的調(diào)用次數(shù),當(dāng)AK的調(diào)用次數(shù)達(dá)到了上限,就不再能夠獲取數(shù)據(jù)了。所以程序程序必須要能智能切換AK,同時為了提高效率,還應(yīng)該多起幾個進(jìn)程進(jìn)行采集任務(wù)。小菜程序還需要花很多精力去完善才能變得健壯起來呢。
代碼的精益求精能使得自己的能力更上一層樓,所以抓取數(shù)據(jù)的活在未來慢慢完善。就寫到這了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容