zoukankan      html  css  js  c++  java
  • python 调用百度地图api接口获取地理详细信息行政代码等

    题目要求:根据单位名称获取具体位置(精确到区县)以及地域行政代码等信息

    解决方法:利用python,调用百度地图API:

           ①通过地理编码服务由得到的单位名称得到经纬度;

             ②再通过逆地理编码服务,由①中得到的经纬度得到单位的具体地理信息(位置,行政代码等)

    一.准备工作

    认证,添加应用,百度地图API注册

     

     

     

     

     二.根据需要选取服务接口(这里选取地理编码服务API以及逆地理编码服务

     在文档中查看如何获取url,以及返回的Json数据格式;

     三.代码实现

    1.根据单位名称获取经纬度

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    # @File  : paqu_area_info.py
    # @Author: 田智凯
    # @Date  : 2020/3/12
    # @Desc  :根据完成单位名称(取第一个)爬取得到省市县以及行政代码
    
    import urllib.request, urllib.parse, urllib.error
    import json
    import hashlib
    
    MyAK = '###'
    MySK = '###'
    
    #处理得到url
    def get_url(name):
        #GET请求 http://api.map.baidu.com/geocoding/v3/?address=北京市海淀区上地十街10号&output=json&ak=您的ak&callback=showLocation
        queryStr = '/geocoding/v3/?address={}&output=json&ak={}'.format(name,MyAK)
        # 对queryStr进行转码,safe内的保留字符不转换
        encodedStr = urllib.parse.quote(queryStr, safe="/:=&?#+!$,;'@()*[]")
        # 在最后追加sk
        rawStr = encodedStr + MySK
        # 计算sn
        sn = (hashlib.md5(urllib.parse.quote_plus(rawStr).encode("utf8")).hexdigest())
        #由于URL里面含有中文,所以需要用parse.quote进行处理,然后返回最终可调用的url
        url = urllib.parse.quote("http://api.map.baidu.com" + queryStr + "&sn=" + sn, safe="/:=&?#+!$,;'@()*[]")
        print('URL:', url)
        return url
    
    #得到json数据
    def get_json(url):
        # 从API读取数据
        req = urllib.request.urlopen(url)
        res = req.read().decode()
    
        # 解析数据
        try:
            # 将 JSON 对象转换为 Python 字典
            json_data = json.loads(res)
        except:
            json_data = None
        if not json_data or 'status' not in json_data or json_data['status'] != 0:
            print('json数据获取失败')
        else:
            #输出Json数据
            print(json.dumps(json_data, indent=4, ensure_ascii=False))
        return json_data
    
    # 获取经纬度坐标
    def get_lnglat(json_data):
        lat = json_data["result"]["location"]["lat"]
        lng = json_data["result"]["location"]["lng"]
        print('纬度', lat, '经度', lng)
    
    if __name__ == '__main__':
        #得到经纬度
        url=get_url('清华大学')
        json_data=get_json(url)
        lnglat=get_lnglat(json_data)
    获取经纬度完整代码

    代码分析:

    ①处理URL:

    #处理得到url
    def get_url(name):#GET请求 http://api.map.baidu.com/geocoding/v3/?address=北京市海淀区上地十街10号&output=json&ak=您的ak&callback=showLocation
        queryStr = '/geocoding/v3/?address={}&output=json&ak={}'.format(name,MyAK)
        # 对queryStr进行转码,safe内的保留字符不转换
        encodedStr = urllib.parse.quote(queryStr, safe="/:=&?#+!$,;'@()*[]")
        # 在最后追加sk
        rawStr = encodedStr + MySK
        # 计算sn
        sn = (hashlib.md5(urllib.parse.quote_plus(rawStr).encode("utf8")).hexdigest())
        #由于URL里面含有中文,所以需要用parse.quote进行处理,然后返回最终可调用的url
        url = urllib.parse.quote("http://api.map.baidu.com" + queryStr + "&sn=" + sn, safe="/:=&?#+!$,;'@()*[]")
        print('URL:', url)
        return url

    ②通过url得到Json数据:

    #得到json数据
    def get_json(url):
        # 从API读取数据
        uh = urllib.request.urlopen(url)
        data = uh.read().decode()
        #print('Retrieved', len(data), 'characters')
    
        # 解析数据
        try:
            # 将 JSON 对象转换为 Python 字典
            json_data = json.loads(data)
        except:
            json_data = None
        if not json_data or 'status' not in json_data or json_data['status'] != 0:
            print('json数据获取失败')
        else:
            #输出Json数据
            print(json.dumps(json_data, indent=4, ensure_ascii=False))
        return json_data

     Json样例:

    ③解析Json数据,得到经纬度:

    # 获取经纬度坐标
    def get_longlat(json_data):
        lat = json_data["result"]["location"]["lat"]
        lng = json_data["result"]["location"]["lng"]
        print('纬度', lat, '经度', lng)

     2.根据经纬度获取详细地理信息

    完整代码:

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    # @File  : paqu_area.py
    # @Author: 田智凯
    # @Date  : 2020/3/12
    # @Desc  :根据完成单位名称(取第一个)爬取得到省市县以及行政代码
    
    import urllib.request, urllib.parse, urllib.error
    import json
    import hashlib
    
    MyAK = '###'
    MySK = '###'
    lat=0.0
    lng=0.0
    #处理得到url
    def get_url(name):
        #GET请求 http://api.map.baidu.com/geocoding/v3/?address=北京市海淀区上地十街10号&output=json&ak=您的ak&callback=showLocation
        queryStr = '/geocoding/v3/?address={}&output=json&ak={}'.format(name,MyAK)
        # 对queryStr进行转码,safe内的保留字符不转换
        encodedStr = urllib.parse.quote(queryStr, safe="/:=&?#+!$,;'@()*[]")
        # 在最后追加sk
        rawStr = encodedStr + MySK
        # 计算sn
        sn = (hashlib.md5(urllib.parse.quote_plus(rawStr).encode("utf8")).hexdigest())
        #由于URL里面含有中文,所以需要用parse.quote进行处理,然后返回最终可调用的url
        url = urllib.parse.quote("http://api.map.baidu.com" + queryStr + "&sn=" + sn, safe="/:=&?#+!$,;'@()*[]")
        #print('URL:', url)
        return url
    
    #得到json数据
    def get_json(url):
        # 从API读取数据
        req = urllib.request.urlopen(url)
        res = req.read().decode()
    
        # 解析数据
        try:
            # 将 JSON 对象转换为 Python 字典
            json_data = json.loads(res)
        except:
            json_data = None
        if not json_data or 'status' not in json_data or json_data['status'] != 0:
            print('json数据获取失败')
        '''else:
            #输出Json数据
            print(json.dumps(json_data, indent=4, ensure_ascii=False))'''
        return json_data
    
    # 获取经纬度坐标
    def get_lnglat(json_data):
        #Python中定义函数时,若想在函数内部对函数外的变量进行操作,就需要在函数内部声明其为global
        global lat,lng
        lat = json_data["result"]["location"]["lat"]
        lng = json_data["result"]["location"]["lng"]
        #print('纬度', lat, '经度', lng)
    
    def get_url2(lat,lng):
        #GET请求 http://api.map.baidu.com/reverse_geocoding/v3/?ak=您的ak&output=json&coordtype=wgs84ll&location=31.225696563611,121.49884033194
        queryStr = '/reverse_geocoding/v3/?ak={}&output=json&coordtype=wgs84ll&location={},{} '.format(MyAK,str(lat),str(lng))
        # 对queryStr进行转码,safe内的保留字符不转换
        encodedStr = urllib.parse.quote(queryStr, safe="/:=&?#+!$,;'@()*[]")
        # 在最后追加sk
        rawStr = encodedStr + MySK
        # 计算sn
        sn = (hashlib.md5(urllib.parse.quote_plus(rawStr).encode("utf8")).hexdigest())
        #由于URL里面含有中文,所以需要用parse.quote进行处理,然后返回最终可调用的url
        url = urllib.parse.quote("http://api.map.baidu.com" + queryStr + "&sn=" + sn, safe="/:=&?#+!$,;'@()*[]")
        #print('URL:', url)
        return url
    
    # 解析Json数据
    def get_info(json_data):
        province=json_data["result"]["addressComponent"]["province"]
        city=json_data["result"]["addressComponent"]["city"]
        district=json_data["result"]["addressComponent"]["district"]
        adcode=json_data["result"]["addressComponent"]["adcode"]
        print("地理:",province+city+district)
        print("行政代码:"+adcode)
    
    if __name__ == '__main__':
        #得到经纬度
        url=get_url('南开大学')
        json_data=get_json(url)
        lnglat=get_lnglat(json_data)
    
        #获取详细信息
        url2=get_url2(lat, lng)
        json_data = get_json(url2)
        get_info(json_data)
    根据单位名称获取详细信息完整代码

    代码分析:(与第一步同理)

    ①处理得到URL

    ②得到Json,样例:

     ③解析Json数据

    ④运行结果:

     四.结合SQL server数据库:读取数据库单位名,将由单位名所得到的行政代码以及具体地理信息加入到数据库中

    解决思路:

    1. 新建area实体,属性:id,单位名称,地理信息,行政代码
    2. 将数据库读取到的id和单位名以及由单位名得到的具体地理信息和行政代码(利用百度API实现)保存在area对象中, 将对象保存在一个list列表中
    3. main中使用多进程运行;迭代list(适用于数据量偏大的)

          我这里八千多条数据开四个进程用时十分钟:

        

    注:

    1. 有的地点,百度地图上是没有的;这里异常处理选择continue;跳过继续读取下一条
    2. 还有就是读取数据库中文乱码问题:
      conn = pymssql.connect("127.0.0.1", "sa", "###", "test", charset="GBK")
    3. 写入数据库中文乱码问题

    conn = pymssql.connect("127.0.0.1", "sa", "###", "test", charset="utf8")

    最后上完整代码:

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    # @File  : paqu_area.py
    # @Author: 田智凯
    # @Date  : 2020/3/12
    # @Desc  :根据完成单位名称(取第一个)爬取得到省市县以及行政代码
    
    import urllib.request, urllib.parse, urllib.error
    import json
    import hashlib
    import pymssql
    import time
    from multiprocessing import Pool
    from paqu.area import Area
    
    
    MyAK = '###'
    MySK = '###'
    lat=0#记录纬度
    lng=0#记录经度
    str_area=0#记录具体地理信息
    adcode=0#记录行政代码
    err=0#记录JSON获取失败数
    
    #百度API地理服务接口;处理得到url
    def get_url(name):
        #GET请求 http://api.map.baidu.com/geocoding/v3/?address=北京市海淀区上地十街10号&output=json&ak=您的ak&callback=showLocation
        queryStr = '/geocoding/v3/?address={}&output=json&ak={}'.format(name,MyAK)
        # 对queryStr进行转码,safe内的保留字符不转换
        encodedStr = urllib.parse.quote(queryStr, safe="/:=&?#+!$,;'@()*[]")
        # 在最后追加sk
        rawStr = encodedStr + MySK
        # 计算sn
        sn = (hashlib.md5(urllib.parse.quote_plus(rawStr).encode("utf8")).hexdigest())
        #由于URL里面含有中文,所以需要用parse.quote进行处理,然后返回最终可调用的url
        url = urllib.parse.quote("http://api.map.baidu.com" + queryStr + "&sn=" + sn, safe="/:=&?#+!$,;'@()*[]")
        #print('URL:', url)
        return url
    
    #根据url得到json数据
    def get_json(url):
        global err
        # 从API读取数据
        req = urllib.request.urlopen(url)
        res = req.read().decode()
    
        # 解析数据
        try:
            # 将 JSON 对象转换为 Python 字典
            json_data = json.loads(res)
        except:
            json_data = None
        if not json_data or 'status' not in json_data or json_data['status'] != 0:
            err=err+1
        '''else:
            #输出Json数据
            print(json.dumps(json_data, indent=4, ensure_ascii=False))'''
        return json_data
    
    #百度API地理服务接口;获取经纬度坐标
    def get_lnglat(json_data):
        #Python中定义函数时,若想在函数内部对函数外的变量进行操作,就需要在函数内部声明其为global
        global lat,lng
        lat = json_data["result"]["location"]["lat"]
        lng = json_data["result"]["location"]["lng"]
        #print('纬度', lat, '经度', lng)
    
    #百度API逆地理服务接口;处理得到url
    def get_url2(lat,lng):
        #GET请求 http://api.map.baidu.com/reverse_geocoding/v3/?ak=您的ak&output=json&coordtype=wgs84ll&location=31.225696563611,121.49884033194
        queryStr = '/reverse_geocoding/v3/?ak={}&output=json&coordtype=wgs84ll&location={},{} '.format(MyAK,str(lat),str(lng))
        # 对queryStr进行转码,safe内的保留字符不转换
        encodedStr = urllib.parse.quote(queryStr, safe="/:=&?#+!$,;'@()*[]")
        # 在最后追加sk
        rawStr = encodedStr + MySK
        # 计算sn
        sn = (hashlib.md5(urllib.parse.quote_plus(rawStr).encode("utf8")).hexdigest())
        #由于URL里面含有中文,所以需要用parse.quote进行处理,然后返回最终可调用的url
        url = urllib.parse.quote("http://api.map.baidu.com" + queryStr + "&sn=" + sn, safe="/:=&?#+!$,;'@()*[]")
        #print('URL:', url)
        return url
    
    # 百度API地理服务接口;解析Json数据;获取行政代码等具体信息
    def get_info(json_data):
        global str_area,adcode
        province=json_data["result"]["addressComponent"]["province"]
        city=json_data["result"]["addressComponent"]["city"]
        district=json_data["result"]["addressComponent"]["district"]
        adcode=json_data["result"]["addressComponent"]["adcode"]
        str_area=province+city+district
        #print("地理:",str_area)
        #print("行政代码:",adcode)
    
    #汇总
    def get_area_main(danwei):
        #得到经纬度
        url=get_url(danwei)
        json_data=get_json(url)
        get_lnglat(json_data)
    
        #获取详细信息
        url2=get_url2(lat, lng)
        json_data = get_json(url2)
        get_info(json_data)
    
    #查询数据库,返回list
    def get_dbdata():
        conn = pymssql.connect("127.0.0.1", "sa", "tzk19991029", "test", charset="GBK")
        cursor = conn.cursor()
        list = []
        try:
            cursor.execute('SELECT id,wc_danwei FROM kettle2')
            for row in cursor:
                area=Area()
                id=row[0]
                danwei=row[1].split()[0]
                try:
                    get_area_main(danwei)
                except:
                    #有的地点百度地图上没有,这时选择跳过去
                    continue
                area.set_id(id)
                area.set_danwei(danwei)
                area.set_area(str_area)
                area.set_adcode(adcode)
                list.append(area)
            cursor.close()
        except:
            # 发生错误时回滚
            conn.rollback()
        return list
    
    #修改数据库表
    def update_dbdata(area):
        conn = pymssql.connect("127.0.0.1", "sa", "tzk19991029", "test", charset="utf8")
        cursor = conn.cursor()
        sql="UPDATE kettle2 SET area='{}',adcode='{}' WHERE id='{}'".format(area.get_area(),area.get_adcode(),area.get_id())
        #print(sql)
        try:
            cursor.execute(sql)
            # 提交到数据库执行
            conn.commit()
            cursor.close()
        except:
            # 发生错误时回滚
            conn.rollback()
    
    if __name__ == '__main__':
        start = time.time()
        list=get_dbdata()
        print(len(list))
        #多进程
        pool = Pool(processes=4)  # 创建进程池
        pool.map(update_dbdata, list)
        pool.close()
        end = time.time()
        print('json数据获取失败数 ', err)
        print("程序用时",end-start)
    项目完整代码
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    # @File  : area.py
    # @Author: 田智凯
    # @Date  : 2020/3/12
    # @Desc  :描述
    
    # 定义类
    
    class Area:
    
        # 定义私有变量
        __id= 0
        __danwei=0
        __area=0
        __adcode=0
    
        # 定义get方法,返回私有变量的值
        def get_id(self):
            return self.__id
        def get_area(self):
            return self.__area
        def get_danwei(self):
            return self.__danwei
        def get_adcode(self):
            return self.__adcode
        # 定义set方法,设置私有变量的值
        def set_id(self, id):
            self.__id = id
        def set_danwei(self, danwei):
            self.__danwei = danwei
        def set_area(self, area):
            self.__area= area
        def set_adcode(self, adcode):
            self.__adcode = adcode
    area实体
  • 相关阅读:
    【火炉炼AI】机器学习003-简单线性回归器的创建,测试,模型保存和加载
    【火炉炼AI】机器学习002-标记编码方法
    【火炉炼AI】机器学习001-数据预处理技术(均值移除,范围缩放,归一化,二值化,独热编码)
    HOJ 13830 DNA Sequencing
    HDU 6078 Wavel Sequence
    hoj 13814 Cake cut
    HDU6071 Lazy Running
    HDU 6070 Dirt Ratio
    HDU 6070 Dirt Ratio
    HDU 6059 Kanade's trio
  • 原文地址:https://www.cnblogs.com/sengzhao666/p/12468554.html
Copyright © 2011-2022 走看看