使用高德開放平臺api批量爬取所需經(jīng)緯度及位置信息(平臺教程和python多進程、多線程代碼詳解)

2019.3.20更新(將代碼升級為非阻塞式多進程监婶,效率極大提升)
2019.6.28更新 (將代碼模塊化旅赢,復用性更強齿桃,使用更高效的線程池進行爬取)

  • 之前寫爬蟲對鏈家某地區(qū)全部二手房信息進行了獲取并存在了MongoDB數(shù)據(jù)庫煮盼。進行數(shù)據(jù)可視化時短纵,想要做基于地圖信息的分析,可所獲信息中未包含經(jīng)緯度值僵控。

  • 經(jīng)過搜索大法香到,發(fā)現(xiàn)原來百度地圖和高德地圖都有開放平臺,可基于文本位置返回更詳細的地理位置信息报破。以高德開發(fā)平臺為例悠就,具體過程如下:

  • 直達鏈接:高德開放平臺

  • 高德開放平臺提供的接口功能很多,這里只是使用"地理/逆地理編碼功能"充易,將結構化地址在經(jīng)緯度之間互轉(zhuǎn)理卑。這里,需要先注冊開發(fā)者賬號并申請一個key(注冊后需先隨便創(chuàng)建一個應用)蔽氨。


    開發(fā)指南頁面
  • 注冊賬號,并創(chuàng)建了一個應用帆疟,獲得一個key密匙鹉究。


    獲得key密匙
  • 然后就可以愉快的使用api獲得經(jīng)緯度啦!
    api請求鏈接為示例:
    "https://restapi.amap.com/v3/geocode/geo?address=北京市朝陽區(qū)阜通東大街6號&output=XML&key=<用戶的key>"

  • 這里只需要替換address為你需要查詢的地點踪宠、替換key為你的key就可以了自赔,我們在瀏覽器中做個試驗:


    api信息返回

    可以看到調(diào)用高德的api接口時能獲得更完整的地理位置信息以及經(jīng)緯度志,親測百度開放平臺的api不會返回更詳細地理信息柳琢,但可以返回該位置的類型绍妨,比如“小區(qū)”之類的〖砹常可視情況選擇他去。

很重要的一點差點忘了,不要以為這可以隨便嗨了倒堕,免費用戶的每日調(diào)用次數(shù)和每秒并發(fā)量是有限制的灾测!
每日調(diào)用限制

百度地圖和高德地圖的每日限量都是相同的,你也可以同時注冊兩邊的賬號垦巴,就像我一樣媳搪,不過對一般需求來說也已經(jīng)足夠了。

  • 下面直接上代碼骤宣,用數(shù)據(jù)庫中的小區(qū)名字來批量獲取經(jīng)緯度和更詳細的地理信息秦爆,邏輯很簡單,傳入小區(qū)名憔披、解析請求就好了:
import pymongo
import pandas as pd
import requests
import re
from multiprocessing import Pool
#數(shù)據(jù)庫連接
client = pymongo.MongoClient("localhost",27017)
db = client['ershoufang']
collection = db["lianjia_solded"]
location = db['locations']

#高德地圖獲取地理信息的api接口
gaode_api_url = "https://restapi.amap.com/v3/geocode/geo?address={}&output=XML&key=YOUR KEY"
headers = {
    "User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36"
}

def get_location_info(loc):
    """
    利用高德開放平臺等限,解析小區(qū)全部位置信息(包含經(jīng)緯度),存入數(shù)據(jù)庫
    :param loc: 小區(qū)名字
    :return: 具體位置信息
    """
    new_loc = "成都市" + loc
    parse_adress_url = gaode_api_url.format(new_loc)
    response = requests.get(parse_adress_url, headers=headers).text
    # 加入判斷防止空白信息返回
    if re.search(r"<count>1</count>", response, re.S):
        # 使用正則表達式提取api反饋的地理信息
        detail_info = re.findall(r"_address>(.*?)</.*?<district>(.*?)</district>.*?<location>(.*?)</location>", response, re.S)[0]
        result = {
            'house_name': loc,
            'adress': detail_info[0],
            'district': detail_info[1],
            'location': detail_info[2],
            'longitude': detail_info[2].split(",")[0],
            'latitude': detail_info[2].split(",")[1]
        }
        # 插入數(shù)據(jù)庫
        location.insert_one(result)
        print(result)
    else:
        print("Something Wrong!未獲取到api信息!")


if __name__ == '__main__':
    #從數(shù)據(jù)庫中獲取源小區(qū)名
    data = pd.DataFrame(list(collection.find())).drop(['elevator', 'url', 'village_id'], axis='columns')
    # 小區(qū)名
    locs = data["village_name"]
    locs_num = pd.value_counts(locs, sort=True)
    #開啟進程池
    p = Pool()
    for loc in locs_num.index[:6000]:  # 高德api限制每天請求不超過6000個
        p.apply_async(get_location_info, (loc,))
    p.close()
    p.join()

6.28更新代碼

import pymongo
import pandas as pd
import requests
import re
from concurrent import futures
from logging import warning

class GaodeLocation(object):
    # 初始化連接到Mongo數(shù)據(jù)庫
    def __init__(self, key, city):
        '''
        初始化連接到數(shù)據(jù)庫
            :param key: 高德開放平臺提供的KEY,需攜帶才能訪問
            :param db: 數(shù)據(jù)庫名
            :param collectin: 存放小區(qū)數(shù)據(jù)的表名
            :param loc_collection: 存放位置信息的新表名
        '''
        self.CITY = city
        self.gaode_api_url = "https://restapi.amap.com/v3/geocode/geo?address={}&output=XML&key=" + key

        self.client = pymongo.MongoClient("localhost", 27017)
        self.db = self.client["ershoufang"]
        self.collection = self.db["lianjia_solded"]
        self.loc_collection = self.db['locations']

    # 將經(jīng)緯度信息存入數(shù)據(jù)庫
    def to_database(self,result):
        return  self.loc_collection.insert_one(result)
    # 傳入位置字符串急灭,通過高德API獲取經(jīng)緯度信息
    def request_info(self,loc):
        detail_loc = CITY + loc
        parse_adress_url = self.gaode_api_url.format(detail_loc)
        response = requests.get(parse_adress_url).text
        # 加入判斷防止空白信息返回
        if re.search(r"<count>1</count>", response, re.S):
            # 提取api反饋的地理信息
            detail_info = re.findall(r"_address>(.*?)</.*?<district>(.*?)</district>.*?<location>(.*?)</location>", response,re.S)[0]
            result = {
                'house_name': loc,
                'adress': detail_info[0],
                'district': detail_info[1],
                'location': detail_info[2],
                'longitude': detail_info[2].split(",")[0],
                'latitude': detail_info[2].split(",")[1]
            }
            print(result)
            self.to_database(result)
        else:
            warning("{}位置信息未成功獲取".format(loc))
            return None

    def main(self):
        # 從數(shù)據(jù)庫中獲取源小區(qū)名
        data = pd.DataFrame(list(self.collection.find())).drop(['elevator', 'url', 'village_id'], axis='columns')
        # 小區(qū)名字段
        locs = data["village_name"]
        # 按小區(qū)名出現(xiàn)頻率排序
        locs_num = pd.value_counts(locs, sort=True)
        # 高德開放平臺一天只允許免費用戶使用API接口6000次......
        available_loc_list = locs_num.index[:6000]

        with futures.ThreadPoolExecutor(max_workers=20) as excutor:
            excutor.map(self.request_info, available_loc_list)

if __name__ == '__main__':
    KEY = "c9ac8XXXXXXXXXXXXXXXXXXX"  # 你的KEY
    CITY = "成都市"    # 你的城市
    s = GaodeLocation(KEY, city=CITY)
    s.main()

模塊化代碼復用性更強禀酱,使用線程池進行批量IO操作,效率進一步提升剩失,

OK,大功告成啦,6000條位置數(shù)據(jù)大概就幾分鐘吧勘畔!


存入數(shù)據(jù)庫中的信息
多進程爬取數(shù)度很快

完。

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末丽惶,一起剝皮案震驚了整個濱河市炫七,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌钾唬,老刑警劉巖万哪,帶你破解...
    沈念sama閱讀 216,919評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異抡秆,居然都是意外死亡奕巍,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,567評論 3 392
  • 文/潘曉璐 我一進店門儒士,熙熙樓的掌柜王于貴愁眉苦臉地迎上來的止,“玉大人,你說我怎么就攤上這事着撩∽绺#” “怎么了?”我有些...
    開封第一講書人閱讀 163,316評論 0 353
  • 文/不壞的土叔 我叫張陵拖叙,是天一觀的道長氓润。 經(jīng)常有香客問我,道長憋沿,這世上最難降的妖魔是什么旺芽? 我笑而不...
    開封第一講書人閱讀 58,294評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮辐啄,結果婚禮上采章,老公的妹妹穿的比我還像新娘。我一直安慰自己壶辜,他們只是感情好悯舟,可當我...
    茶點故事閱讀 67,318評論 6 390
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著砸民,像睡著了一般抵怎。 火紅的嫁衣襯著肌膚如雪奋救。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,245評論 1 299
  • 那天反惕,我揣著相機與錄音尝艘,去河邊找鬼。 笑死姿染,一個胖子當著我的面吹牛背亥,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播悬赏,決...
    沈念sama閱讀 40,120評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼狡汉,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了闽颇?” 一聲冷哼從身側(cè)響起盾戴,我...
    開封第一講書人閱讀 38,964評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎兵多,沒想到半個月后尖啡,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,376評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡剩膘,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,592評論 2 333
  • 正文 我和宋清朗相戀三年可婶,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片援雇。...
    茶點故事閱讀 39,764評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖椎扬,靈堂內(nèi)的尸體忽然破棺而出惫搏,到底是詐尸還是另有隱情,我是刑警寧澤蚕涤,帶...
    沈念sama閱讀 35,460評論 5 344
  • 正文 年R本政府宣布筐赔,位于F島的核電站,受9級特大地震影響揖铜,放射性物質(zhì)發(fā)生泄漏茴丰。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,070評論 3 327
  • 文/蒙蒙 一天吓、第九天 我趴在偏房一處隱蔽的房頂上張望贿肩。 院中可真熱鬧,春花似錦龄寞、人聲如沸汰规。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,697評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽溜哮。三九已至滔金,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間茂嗓,已是汗流浹背餐茵。 一陣腳步聲響...
    開封第一講書人閱讀 32,846評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留述吸,地道東北人忿族。 一個月前我還...
    沈念sama閱讀 47,819評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像刚梭,于是被迫代替她去往敵國和親肠阱。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,665評論 2 354