python利用百度地图api获取poi点地址、坐标数据

python 专栏收录该内容
1 篇文章 0 订阅

1.目标

百度地图API是为开发者免费提供的一套基于百度地图服务的应用接口,使用百度地图API需要注册百度账号,通过百度地图开发者认证,在控制台新建自己的应用,获得密钥。本文主要讲获取到密钥之后的操作,编写python3脚本利用百度地图API获取poi地址和坐标点,并进行数据保存。
百度地图开放平台:http://lbsyun.baidu.com/apiconsole/key?application=key
API接口文档:http://lbsyun.baidu.com/index.php?title=webapi/place-suggestion-api

2.步骤

  1. 构建查询条件
  2. 构建url
  3. 发送请求获取数据
  4. 解析数据
  5. 存储数据

3.具体操作

在百度地图开放平台获取到ak和sk之后,进行下面的操作。
在这里插入图片描述

3.1构建查询条件

构建查询条件可以通过两种方式:

  1. 用key,value方式组建之后转码,如:
 kwd = {"query": "ATM机","tag":"银行","region": "224","output": "json", "ak": ak,"city_limit":"true"}
 query_str=‘/place/v2/search?{}’.format(urllib.parse.urlencode(kwd))
  1. 手动拼接url再转码
 queryStr = '/place/v2/search/?query=%s&output=json&ak=%s&region=131' % (“苏州拙政园”,ak)
 encodedStr = urllib.parse.quote(queryStr, safe="/:=&?#+!$,;'@()*[]")

ps:我一般用第二种,用确定的名称去query,如“苏州拙政园”,“上海迪士尼”

3.2生成sn,构建url

我们获取到的ak直接加到url里面,但是sk要经过加密生成sn才能使用
在这里插入图片描述
sn生成方式(官方代码):

# -*- coding: utf-8 -*- 
# 第一行必须有,否则报中文字符非ascii码错误
import urllib
import hashlib

# 以get请求为例http://api.map.baidu.com/geocoder/v2/?address=百度大厦&output=json&ak=yourak
queryStr = '/geocoder/v2/?address=百度大厦&output=json&ak=yourak'

# 对queryStr进行转码,safe内的保留字符不转换
encodedStr = urllib.quote(queryStr, safe="/:=&?#+!$,;'@()*[]")

# 在最后直接追加上yoursk
rawStr = encodedStr + 'yoursk'

# md5计算出的sn值7de5a22212ffaa9e326444c75a58f9a0
# 最终合法请求url是http://api.map.baidu.com/geocoder/v2/?address=百度大厦&output=json&ak=yourak&sn=7de5a22212ffaa9e326444c75a58f9a0
print hashlib.md5(urllib.quote_plus(rawStr)).hexdigest()

说明:http://lbsyun.baidu.com/index.php?title=lbscloud/api/appendix

3.3发送请求获取数据

用requests发送请求即可

r= requests.get(url, data=data, headers=headers)
print(r.text)
数据格式:
json_demo = """
       {
       "status":0,
       "message":"ok",
       "results":[
        {
            "name":"观承别墅",
            "location":{
                "lat":40.131049,
                "lng":116.499987
            },
            "address":"北京市顺义区京承高速8号出口右转,直行100米过法式大桥即右转,规划六路附近",
            "province":"北京市",
            "city":"北京市",
            "area":"顺义区",
            "street_id":"74b0f2f0ec56f7dcdbd891db",
            "telephone":"(010)60469999",
            "detail":1,
            "uid":"74b0f2f0ec56f7dcdbd891db"
        }
    ]
}
"""

3.4解析数据

用json的loads方法解析数据,将数据以k,v的方式存储,便于取出需要的字段。

json_dict = json.loads(data)
for (k, v) in json_dict.items():
    print(k,  " : " , v)

3.5存储数据

存储数据通常将一行数据存入一个list,再将每个list存到一个list中,作为一页数据,总体结构就是[[],[],[],[]…]
可将数据存入csv或者excel
存入csv较为简单,但是会乱码(第一次打开后最好转存为excel),可以设置各种读写方式,w是写入,a+是追加

with open(path,'a+',newline='',encoding='utf-8-sig')as f:
    f_csv = csv.writer(f)
    f_csv.writerows(data)

存入excel,包括创建excel存入数据和打开excel追加数据

#创建存入
f = xlwt.Workbook()
sheet1 = f.add_sheet(u'sheet1',cell_overwrite_ok=False) 
i = 0
for data in datas:
    for j in range(len(data)):
        sheet1.write(i,j,str(data[j]))
    i = i + 1        
f.save(path)

#打开追加
index = len(datas)
workbook = xlrd.open_workbook(path)
worksheet = workbook.sheet_by_name(u'sheet1')
rows_old = worksheet.nrows 
new_workbook = copy(workbook) 
new_worksheet = new_workbook.get_sheet(0)    
for i in range(index):
    for j in range(len(datas[i])):
        new_worksheet.write(i+rows_old, j, str(datas[i][j]))     
new_workbook.save(path)

4.应用

我通过以上方法获取了江苏省养殖场的数据,首先在百度地图页面爬取江苏省各市养殖场的名称,将其存在一张excel中,再按照名称构建url请求数据获取地址和坐标(感觉名称检索精确一点),我保存的数据是检索出记录的第一条。以下是我的代码:

# -*- coding: utf-8 -*- 
import urllib
import hashlib
import json,csv,xlrd,xlwt,requests,xlutils,os
from xlutils.copy import copy 

#发送请求
def sendUrl( url, headers, ad,data=None):
    r= requests.get(url, data=data, headers=headers)
    print(r.text)
    return r.text           

#保存数据至csv(容易乱码)      
def saveAsCSV(data,path):
    #追加"a+"
    with open(path,'a+',newline='',encoding='utf-8-sig')as f:
        f_csv = csv.writer(f)
        f_csv.writerows(data)

#保存数据至excel
def saveAsExcel(path, datas):
    if os.path.exists(path):
        append2xls(path,datas)
        return
    f = xlwt.Workbook()
    sheet1 = f.add_sheet(u'sheet1',cell_overwrite_ok=False) 
    i = 0
    for data in datas:
        for j in range(len(data)):
            sheet1.write(i,j,str(data[j]))
        i = i + 1        
    f.save(path)

#向excel追加记录
def append2xls(path,datas):
    index = len(datas)
    workbook = xlrd.open_workbook(path)
    worksheet = workbook.sheet_by_name(u'sheet1')
    rows_old = worksheet.nrows 
    new_workbook = copy(workbook) 
    new_worksheet = new_workbook.get_sheet(0)  
    
    for i in range(index):
        for j in range(len(datas[i])):
            new_worksheet.write(i+rows_old, j, str(datas[i][j]))     
    new_workbook.save(path)
    
#读取excel
def readExcel(path):
    data = xlrd.open_workbook(path)
    sheets = data.sheets()
    data_list=[]
    for i in range(len(sheets)):
        table=data.sheets()[i]
        table_rows=table.nrows
        table_cols=table.ncols       
        for j in range(table_rows):
            data_list.append( table.cell(j,2).value)#此处的数字是列号,起始值是0
    #print(data_list)
    return data_list

#解析json并保存     
def parseJson(data,path):
    json_dict = json.loads(data)
    #print(json_dict)
    list_data=[]
    for (k, v) in json_dict.items():
        #print(k,  " : " , v)
        if k=="results":  
          for data in v:         
            list_row=[]
            #list_row.insert(4,ad)
            for (data_k, data_v) in data.items():
                if data_k=="name":
                   list_row.insert(0,data_v)               
                if data_k=="location":
                   list_row.insert(1,data_v)                                  
                if data_k=="address":
                   list_row.insert(2,data_v)
                '''
                if data_k=="area":
                   list_row.insert(3,data_v)
                '''
            #print(list_row)
            list_data.append(list_row)
            break#只要第一条
    saveAsExcel(path,list_data)
    
#获取url    
def getUrlByName(name,ak,sk):
    queryStr = '/place/v2/search/?query=%s&output=json&ak=%s&region=131' % (name,ak)
    encodedStr = urllib.parse.quote(queryStr, safe="/:=&?#+!$,;'@()*[]")
    rawStr = encodedStr + sk
    sn = (hashlib.md5(urllib.parse.quote_plus(rawStr).encode("utf8")).hexdigest())
    url = urllib.parse.quote("http://api.map.baidu.com" + queryStr + "&sn=" + sn, safe="/:=&?#+!$,;'@()*[]")
    return url

#获取url
def getUrlByStr(queryStr,sk):
    encodedStr = urllib.parse.quote(queryStr, safe="/:=&?#+!$,;'@()*[]")
    rawStr = encodedStr + sk
    sn = (hashlib.md5(urllib.parse.quote_plus(rawStr).encode("utf8")).hexdigest())
    url = urllib.parse.quote("http://api.map.baidu.com" + queryStr + "&sn=" + sn, safe="/:=&?#+!$,;'@()*[]")
    return url

def Main():
    headers = {
        'User-Agent': "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36"}
    
    #需自行注册 百度地图开发者 在控制台新建应用获取到ak和sk
    ak = "N1hfnVs74YgFkCPmVKe0VshQKUufWuOK"
    sk="Qy73k6nrcM25OHrfdVSePHULpWnHki0F"
    
    ''' 
    #根据一个名称查询
    url=getUrlByName("苏州拙政园",ak,sk)
    data=sendUrl(url, headers,"")
    parseJson(data,r"D:\0testdata\爬虫\百度地图poi爬取\苏州.xls")

    #构造查询条件,tag有固定的类别不能乱写,region有区域代码
    kwd = {"query": "ATM机","tag":"银行","region": "224","output": "json", "ak": ak,"city_limit":"true"}
    query_str="/place/v2/search?{}".format(urllib.parse.urlencode(kwd))
    url=getUrlByStr(query_str,sk)
    data=sendUrl(url, headers,"")
    parseJson(data,"aaa.xls")
    '''
    
    #根据excel里面的一列名称查询
    name_list=readExcel(r'D:\江苏省养殖名称\常州.xlsx')
    for i in name_list:      
        url=getUrlByName(i,ak,sk)
        print(url)
        data=sendUrl(url, headers,i)
        parseJson(data,"常州.xls")    
    
if __name__ == '__main__':
    Main()

爬下来的数据:
在这里插入图片描述
That’s all!
祝大家顺利!

  • 0
    点赞
  • 0
    评论
  • 8
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值