左手用R右手Python系列——百度地图API调用与地址解析/逆解析

时间:2022-05-08
本文章向大家介绍左手用R右手Python系列——百度地图API调用与地址解析/逆解析,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

地理位置信息的解析与逆解析可能是我们在分析地理位置数据时所面临的最棘手的问题了,好在现在很多主流的在线 地图厂商地给开发者提供了免费的API接口调用。

这一篇以百度地图API为例,演示如何在R语言以及Python中通过调用API实现地理位置的解析与逆解析,即将地址转换为具体经纬度,将经纬度转换为具体的地址。

免费API调用需要开发者自己在百度地图开放平台上注册APPkey,每日限调6000次,因为是免费的,所有人都可以申请注册,注册地址如下。

http://lbsyun.baidu.com/apiconsole/key

以下是本次分享的所有代码:

R语言版:

library("httr") 
library("magrittr") 
library("jsonlite")
dizhi = c('北京市朝阳区望京东路6号望京国际研发园三期','北京市海淀区上地信息路9号奎科科技大厦')

将地址解析为具体的经纬度:

GetJD <- function(address){
    url = "http://api.map.baidu.com/geocoder/v2/"
    header  <- c("User-Agent"="Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36")
     payload = list(
         'output' = 'json', 
        'ak' = '***********'
         )
     addinfo <- data.frame()
     for (i in dizhi){
         payload[["address"]]=i
         tryCatch({
              web <- GET(url,add_headers(.headers = header),query = payload)
             content <- web %>% content(as="text",encoding="UTF-8") %>% fromJSON(flatten = TRUE) %>% `[[`(2) %>% `[[`(1)
             addinfo <- rbind(addinfo,content)
         },error = function(e){
             cat(sprintf("任务【%s】处理失败!",i),sep = "n")
             addinfo <- rbind(addinfo,list("lng" = NA ,"lat" = NA))
          })
         Sys.sleep(runif(1))
         print(sprintf("正在抓取第【%s】个地址",i))
         }
     print("所有数据全部抓取完毕!!!")
     return(addinfo) 
   }

运行程序:

system.time(myresult<-GetJD(dizhi))

lng    lat
116.4955    40.01256
116.3130    40.04769

地址逆解析——将经纬度还原为具体地址

待解析的经纬度指标

lddata = data.frame(
       lon = c(39.934,40.013,40.047),
       lat = c(116.329,116.495,116.313)
    )

解析函数

GetAddress <- function(lddata){
    url = "http://api.map.baidu.com/geocoder/v2/"
    header = c('User-Agent'= 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36')
    payload = list(
        'output' = 'json', 
        'ak' = '*******'
        ) 
    addinfo = c() 
    for (i in 1:nrow(lddata)){
        payload[['location']] = sprintf('%.3f,%.3f',lddata[i,'lon'],lddata[i,'lat'])
        tryCatch({
            web <-  GET(url,add_headers(.headers = header),query = payload)
            addinfo <- web %>% content(as="text",encoding="UTF-8") %>% fromJSON(flatten = TRUE) %>%[[(2) %>%[[`(2) %>% c(addinfo,.)
       },error = function(e){
           cat(sprintf(“第【%d】个任务处理失败!”,i),sep = “n”)
           addinfo <- c(addinfo,NA)
       })

    } 
   return(addinfo)
}
运行逆解析程序
system.time( MyAddress<-GetAddress(lddata))
'北京市海淀区增光路35-6号' '北京市朝阳区望京东路辅路' '北京市海淀区上地五街9号'

Python版:

import  time
import requests
from urllib.request import quote
#待解析的地址
dizhi = ['北京市朝阳区望京东路6号望京国际研发园三期','北京市海淀区上地信息路9号奎科科技大厦']

地址解析函数——将地址转换为经纬度

def getid(dizhi):
    url = "http://api.map.baidu.com/geocoder/v2/"
    header = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36'}
    payload = {
        'output':'json',
        'ak':'**********'
        }
    addinfo = []
    for i in dizhi:
        payload['address'] = i
        try:
            content =  requests.get(url,params=payload,headers=header).json()
            addinfo.append(content['result']['location'])
        except:
            pass
    return(addinfo)

运行解析程序

if __name__ == "__main__":
    #计时开始:
    t0 = time.time()
    myaddress = getid(dizhi)
    t1 = time.time()
    total = t1 - t0
    print("消耗时间:{}".format(total))

[{'lat': 40.012564990769135, 'lng': 116.49546484496102},
 {'lat': 40.04768803728198, 'lng': 116.31300123279135}]

地址逆解析——经纬度解析为具体地址

lon = [39.934,40.013,40.047]
lat = [116.329,116.495,116.313]
lddata = [(j,w) for j,w in zip(lon,lat)]

解析函数

def GetAddress(lddata):
    url = "http://api.map.baidu.com/geocoder/v2/"
    header = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36'}
    payload = {
        'output':'json',
        'ak':'*********'
        }
    addinfo = []
    for lon,lat in lddata:
        payload['location'] = '{0:s},{1:s}'.format(str(lon),str(lat))
        try:
            content =  requests.get(url,params=payload,headers=header).json()
            addinfo.append(content['result']['formatted_address'])
        except:
            addinfo.append(None)
    return(addinfo)

运行程序

if __name__ == "__main__":    
    #计时开始:
    t0 = time.time()
    mylonlat = GetAddress(lddata)
    t1 = time.time()
    total = t1 - t0
    print("消耗时间:{}".format(total))
['北京市海淀区增光路35-6号', '北京市朝阳区望京东路辅路', '北京市海淀区上地五街9号']