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

最近公司需要抓取百度地圖中所有藥店數(shù)據(jù),本人比較愚笨纽匙,斷斷續(xù)續(xù)花了2天時間才完成此次任務(wù)。期間遇到的各種小坑插爹,但目前進度良好。以下記錄的是我進行任務(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)用默認只返回10條信息,所以為了能夠獲得更多的信息感猛,需要設(shè)置page_num參數(shù)進行翻頁操作七扰。這時候使用一個遞歸函數(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條,這遠遠是不夠的司致。一個大城市的藥店總數(shù)能超過5000拆吆,而一些二線城市的藥店總數(shù)也能接近一千≈茫看來百度在API上做了手腳枣耀,強行阻止了用戶扒她的數(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)存,爆出嚴重錯誤机错。因此爬范,需要在調(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ù)達到了上限镀裤,就不再能夠獲取數(shù)據(jù)了。所以程序程序必須要能智能切換AK缴饭,同時為了提高效率暑劝,還應(yīng)該多起幾個進程進行采集任務(wù)。小菜程序還需要花很多精力去完善才能變得健壯起來呢茴扁。
代碼的精益求精能使得自己的能力更上一層樓铃岔,所以抓取數(shù)據(jù)的活在未來慢慢完善汪疮。就寫到這了峭火。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末毁习,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子卖丸,更是在濱河造成了極大的恐慌纺且,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,542評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件稍浆,死亡現(xiàn)場離奇詭異载碌,居然都是意外死亡,警方通過查閱死者的電腦和手機衅枫,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,596評論 3 385
  • 文/潘曉璐 我一進店門嫁艇,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人弦撩,你說我怎么就攤上這事步咪。” “怎么了益楼?”我有些...
    開封第一講書人閱讀 158,021評論 0 348
  • 文/不壞的土叔 我叫張陵猾漫,是天一觀的道長。 經(jīng)常有香客問我感凤,道長悯周,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,682評論 1 284
  • 正文 為了忘掉前任陪竿,我火速辦了婚禮禽翼,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘萨惑。我一直安慰自己捐康,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,792評論 6 386
  • 文/花漫 我一把揭開白布庸蔼。 她就那樣靜靜地躺著解总,像睡著了一般。 火紅的嫁衣襯著肌膚如雪姐仅。 梳的紋絲不亂的頭發(fā)上花枫,一...
    開封第一講書人閱讀 49,985評論 1 291
  • 那天,我揣著相機與錄音掏膏,去河邊找鬼劳翰。 笑死,一個胖子當(dāng)著我的面吹牛馒疹,可吹牛的內(nèi)容都是我干的佳簸。 我是一名探鬼主播,決...
    沈念sama閱讀 39,107評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼生均!你這毒婦竟也來了听想?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,845評論 0 268
  • 序言:老撾萬榮一對情侶失蹤马胧,失蹤者是張志新(化名)和其女友劉穎汉买,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體佩脊,經(jīng)...
    沈念sama閱讀 44,299評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡蛙粘,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,612評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了威彰。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片出牧。...
    茶點故事閱讀 38,747評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖歇盼,靈堂內(nèi)的尸體忽然破棺而出崔列,到底是詐尸還是另有隱情,我是刑警寧澤旺遮,帶...
    沈念sama閱讀 34,441評論 4 333
  • 正文 年R本政府宣布赵讯,位于F島的核電站,受9級特大地震影響耿眉,放射性物質(zhì)發(fā)生泄漏边翼。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,072評論 3 317
  • 文/蒙蒙 一鸣剪、第九天 我趴在偏房一處隱蔽的房頂上張望组底。 院中可真熱鬧,春花似錦筐骇、人聲如沸债鸡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,828評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽厌均。三九已至,卻和暖如春告唆,著一層夾襖步出監(jiān)牢的瞬間棺弊,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,069評論 1 267
  • 我被黑心中介騙來泰國打工擒悬, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留模她,地道東北人。 一個月前我還...
    沈念sama閱讀 46,545評論 2 362
  • 正文 我出身青樓懂牧,卻偏偏與公主長得像侈净,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,658評論 2 350

推薦閱讀更多精彩內(nèi)容