天天看點

python利用百度API進行地理編碼(将地名轉換為經緯度資訊)

更新時間:2018-3-28

更新内容:優化部分代碼,添加mongodb部分的内容

本文章通過講解如何在百度地圖API申請密鑰,然後在python中調用API接口将自有資料中的地名轉換為經緯度坐标。

運作環境: python3

一、注冊密鑰

在百度地圖API上相關位置的展現是以經緯度為基礎的。要使用百度地圖接口需要注冊百度地圖API以擷取免費的密鑰,才能完全使用該API。登入網址:http://lbsyun.baidu.com/,

首頁點選申請密鑰按鈕,經過填寫個人資訊、郵箱注冊等,成功之後在開放平台上點選“建立應用”,填寫相關資訊,應用名稱可随意填寫,應用類型根據自己需要進行設定,若是做安卓開發則選擇Android SDK,本應用中因為是通過浏覽器端進行調用,是以選擇浏覽器端。在這裡特别說明的是,在IP白名單框裡,如果不清楚自己的IP位址,最好設定為:0.0.0.0/0,雖然百度提醒它會有洩露使用的風險,但是有時候你把你自己的IP位址輸進去可能也不行。送出後,在你建立應用的通路應用(AK)那一欄就是你的密鑰。

二、利用申請好的密鑰擷取經緯度坐标

注冊好密鑰後就可以使用百度Web服務API下的Geocoding API接口來擷取你所需要位址的經緯度坐标并轉化為json結構的資料,開發文檔連結為Geocoding API,該文檔中有一些參數的說明,如果需求和本文不太一緻,可前往該頁面了解每個參數的作用并進行修改以擷取需要的效果。

下面是根據位址擷取經緯度的函數。傳入地名,傳回緯度,經度

import json
from urllib.request import urlopen, quote
import requests
def getlnglat(address):
    url = 'http://api.map.baidu.com/geocoder/v2/'
    output = 'json'
    ak = '申請好的密鑰' # 浏覽器端密鑰
    address = quote(address) # 由于本文位址變量為中文,為防止亂碼,先用quote進行編碼
    uri = url + '?' + 'address=' + address  + '&output=' + output + '&ak=' + ak 
    req = urlopen(uri)
    res = req.read().decode() 
    temp = json.loads(res)
    lat = temp['result']['location']['lat']
    lng = temp['result']['location']['lng']
    return lat, lng
           

三、讀取資料批量擷取經緯度

{"種類": "火鍋", "商家名稱": "沸爐火鍋·道地的川味火鍋(懷柔...", "電話": "  010-60686895", "營業時間": "10:00-21:00 周一至周日", "評分": , "位址": "北京市懷柔區府前西街2号新悅百貨四樓", "連結": "http://www.dianping.com/shop/70861885", "人均消費": , "評論數量": "261"}
{"種類": "北京菜", "商家名稱": "青龍山莊", "電話": "  13141427145", "營業時間": "全天 周一至周日", "評分": , "位址": "北京市懷柔區懷北鎮河防口村青龍峽道口公交站東800米", "連結": "http://www.dianping.com/shop/68040161", "人均消費": , "評論數量": "15"}
           

本文中讀取的資料為上述類型的json資料,讀取每一行資料到一個字典中,将字典中的位址資料傳給上文中的參數,擷取傳回的經緯度,并寫入字典中,存儲為新的資料。

完整代碼為:

#-*-coding:utf-8-*-
# getlonlat.py
# from: mamq
# run: python3 getlonlat.py
from urllib.request import urlopen, quote
from pymongo import MongoClient
import json
import codecs
import sys
import os

path = sys.path[] + os.sep

def getlnglat(address):
    """根據傳入地名參數擷取經緯度"""
    url = 'http://api.map.baidu.com/geocoder/v2/'
    output = 'json'
    ak = '申請好的密鑰' # 浏覽器端密鑰
    address = quote(address) 
    uri = url + '?' + 'address=' + address  + '&output=' + output + '&ak=' + ak 
    req = urlopen(uri)
    res = req.read().decode() 
    temp = json.loads(res)
    lat = temp['result']['location']['lat']
    lng = temp['result']['location']['lng']
    return lat, lng

def jsondump(outfilename, dic):
    """傳入儲存路徑和字典參數,儲存資料到對應的檔案中"""
    with codecs.open(path + outfilename + '.json', 'a', 'utf-8') as outfile:
        json.dump(dic, outfile, ensure_ascii=False)
        outfile.write('\n')

def convertfile(filename):
    file = codecs.open(path + filename, 'r', encoding='utf-8')
    outfilename = 'loc' + filename
    for line in file:
        dic = json.loads(line.strip())
        address = dic['位址']
        dic['lat'], dic['lng'] = getlnglat(address)
        jsondump(outfilename, dic)

def convertmongodb(host, dbname, collname):
    '''連接配接mongodb, 并根據其位置字段得到其坐标資訊,進而更新資料庫'''
    client = MongoClient(host, )   
    db = client[dbname]
    collection = db[collname]
    for dic in collection.find():
        dic['lat'], dic['lng'] = getlnglat(dic['位址'])
        collection.save(dic) # 更新資料,并覆寫相同_id的記錄
    print (dic)

if __name__ == '__main__':
    filename = '/home/mamq/test.json'
    # convertfile(filename)
    host = '192.168.1.101' # 需要連接配接的資料庫所在ip
    dbname = 'landPlan'
    collname = 'xian'
    convertmongodb(host, dbname, collname)
           

參考資料:

[1]:Geocoding API:Web服務API