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實體

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM