Python调用高德地图API实现JS网页地图显示的完整代码示例
作者:无人装备硬件开发爱好者
1 概述
本文将详细介绍如何使用Python开发调用高德地图API,并在JavaScript网页中显示地图。我们将从基础知识开始,逐步深入,最后提供一个完整的实现方案。内容包括高德地图API的申请、Python后端服务的开发、前端JavaScript地图显示以及前后端数据交互。文章将尽量使用表格方式呈现关键信息,确保内容通俗易懂。
高德地图API提供了丰富的地图服务,包括地理编码、逆地理编码、路径规划、地点搜索等功能3。通过Python调用这些API,我们可以实现地理位置数据的处理和分析,然后通过JavaScript在网页上可视化展示结果。
1.1 高德地图API简介
高德地图开放平台为开发者提供了多种API服务,主要包括:
Web服务API:提供地理编码、逆地理编码、路径规划等功能,可通过HTTP请求调用1。
JavaScript API:用于在网页中显示地图、添加标记、绘制图形等2。
其他API:如Android SDK、iOS SDK等,用于移动应用开发。
本文将重点介绍如何使用Python调用Web服务API处理地理数据,以及如何使用JavaScript API在网页中显示地图。
2 准备工作
2.1 申请高德地图API Key
使用高德地图API前,需要申请API Key。具体步骤如下13:
注册高德开发者账号
访问高德开放平台,注册账号。创建应用
登录后进入控制台,选择"应用管理" -> "我的应用" -> "创建新应用"。添加Key
在应用详情中点击"添加Key",选择"Web服务"作为服务平台。如果需要在前端显示地图,还需创建一个Key并选择"Web端(JSAPI)"作为服务平台。获取Key
创建成功后,将获得一个API Key,后续调用API时需使用此Key。
2.2 安装必要的Python库
Python调用高德地图Web服务API主要使用requests
库发送HTTP请求3。安装命令如下:
bash
pip install requests
对于前端部分,我们需要使用HTML和JavaScript来显示地图。不需要额外安装库,只需在HTML中引入高德地图JavaScript API即可。
3 Python调用高德地图Web服务API
高德地图Web服务API提供了多种功能,以下介绍几个常用功能的调用方法。
3.1 地理编码
地理编码是将结构化地址转换为经纬度坐标的过程13。
API地址:https://restapi.amap.com/v3/geocode/geo
请求参数:
参数名 | 含义 | 是否必须 | 说明 |
---|---|---|---|
key | API Key | 是 | 申请的唯一标识 |
address | 地址 | 是 | 结构化地址信息 |
city | 城市 | 否 | 指定查询城市,可选中文、拼音、citycode或adcode |
output | 输出格式 | 否 | 可选json或xml,默认json |
Python代码示例:
python
import requests import json def geocode(address, city=None, api_key='your_api_key'): url = 'https://restapi.amap.com/v3/geocode/geo' params = { 'key': api_key, 'address': address, 'output': 'json' } if city: params['city'] = city response = requests.get(url, params=params) data = response.json() if data['status'] == '1' and int(data['count']) > 0: location = data['geocodes'][0]['location'] longitude, latitude = location.split(',') return longitude, latitude else: return None, None # 使用示例 api_key = '你的API Key' address = '北京市朝阳区阜通东大街6号' lng, lat = geocode(address, api_key=api_key) print(f'经纬度:经度={lng}, 纬度={lat}')
返回结果示例:
json
{ "status": "1", "info": "OK", "infocode": "10000", "count": "1", "geocodes": [ { "formatted_address": "北京市朝阳区阜通东大街6号", "country": "中国", "province": "北京市", "citycode": "010", "city": "北京市", "district": "朝阳区", "township": [], "neighborhood": {"name": [], "type": []}, "building": {"name": [], "type": []}, "adcode": "110105", "street": "阜通东大街", "number": "6号", "location": "116.480881,39.989410", "level": "门牌号" } ] }
3.2 逆地理编码
逆地理编码是将经纬度坐标转换为结构化地址的过程13。
API地址:https://restapi.amap.com/v3/geocode/regeo
请求参数:
参数名 | 含义 | 是否必须 | 说明 |
---|---|---|---|
key | API Key | 是 | 申请的唯一标识 |
location | 经纬度 | 是 | 格式为"经度,纬度" |
radius | 搜索半径 | 否 | 单位:米,取值范围0-3000,默认1000 |
extensions | 返回结果扩展 | 否 | 可选base或all,默认base |
poitype | POI类型 | 否 | 逆地理编码时返回的POI类型 |
roadlevel | 道路等级 | 否 | 可选0或1,需extensions=all时生效 |
Python代码示例:
python
def regeocode(location, api_key='your_api_key', extensions='base'): url = 'https://restapi.amap.com/v3/geocode/regeo' params = { 'key': api_key, 'location': location, 'extensions': extensions, 'output': 'json' } response = requests.get(url, params=params) data = response.json() if data['status'] == '1': return data['regeocode'] else: return None # 使用示例 location = '116.480881,39.989410' address_component = regeocode(location, api_key=api_key) print(address_component)
3.3 路径规划
高德地图提供了多种路径规划API,包括驾车、步行、骑行等13。以下以驾车路径规划为例。
API地址:https://restapi.amap.com/v3/direction/driving
请求参数:
参数名 | 含义 | 是否必须 | 说明 |
---|---|---|---|
key | API Key | 是 | 申请的唯一标识 |
origin | 起点 | 是 | 格式为"经度,纬度" |
destination | 终点 | 是 | 格式为"经度,纬度" |
strategy | 策略选择 | 否 | 0-速度最快,1-费用最低,2-距离最短,3-不走高速,4-避免拥堵,5-多策略 |
waypoints | 途经点 | 否 | 格式为"经度,纬度;经度,纬度;..." |
Python代码示例:
python
def driving_route(origin, destination, api_key='your_api_key', strategy=0): url = 'https://restapi.amap.com/v3/direction/driving' params = { 'key': api_key, 'origin': origin, 'destination': destination, 'strategy': strategy, 'output': 'json' } response = requests.get(url, params=params) data = response.json() if data['status'] == '1': route = data['route'] path = route['paths'][0] distance = path['distance'] # 总距离,米 duration = path['duration'] # 总时间,秒 steps = path['steps'] # 步骤列表 return distance, duration, steps else: return None, None, None # 使用示例 origin = '116.481028,39.989643' destination = '116.434446,39.90816' distance, duration, steps = driving_route(origin, destination, api_key=api_key) print(f'距离:{distance}米,时间:{duration}秒')
3.4 周边搜索
周边搜索用于查找指定位置周围的兴趣点(POI)37。
API地址:https://restapi.amap.com/v3/place/around
请求参数:
参数名 | 含义 | 是否必须 | 说明 |
---|---|---|---|
key | API Key | 是 | 申请的唯一标识 |
location | 中心点 | 是 | 格式为"经度,纬度" |
keywords | 关键字 | 否 | 多个关键字用"|"分隔 |
types | 类型 | 否 | POI类型代码,多个类型用"|"分隔 |
radius | 搜索半径 | 否 | 单位:米,最大值30000,默认3000 |
offset | 每页记录数 | 否 | 每页记录数,最大值25,默认20 |
page | 页码 | 否 | 当前页码,默认1 |
Python代码示例:
python
def search_around(location, keywords=None, types=None, radius=3000, api_key='your_api_key'): url = 'https://restapi.amap.com/v3/place/around' params = { 'key': api_key, 'location': location, 'radius': radius, 'output': 'json' } if keywords: params['keywords'] = keywords if types: params['types'] = types response = requests.get(url, params=params) data = response.json() if data['status'] == '1': return data['pois'] else: return [] # 使用示例 location = '116.480881,39.989410' pois = search_around(location, keywords='餐馆', api_key=api_key) for poi in pois: print(f"名称:{poi['name']},地址:{poi['address']},距离:{poi['distance']}米")
4 前端JavaScript地图显示
在处理完地理数据后,我们需要在前端网页中显示地图和结果。高德地图JavaScript API提供了丰富的地图显示和交互功能24。
4.1 引入高德地图JavaScript API
在HTML文件中引入高德地图JavaScript API:
html
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>高德地图示例</title> <style> #map-container { width: 100%; height: 500px; } </style> </head> <body> <div id="map-container"></div> <script src="https://webapi.amap.com/maps?v=2.0&key=你的JSAPI_KEY"></script> <script> // 地图初始化代码将在这里编写 </script> </body> </html>
4.2 初始化地图
使用JavaScript初始化地图:
javascript
// 初始化地图 var map = new AMap.Map('map-container', { zoom: 13, // 缩放级别 center: [116.397428, 39.90923], // 中心点坐标 viewMode: '2D' // 使用2D视图 }); // 添加控件 map.addControl(new AMap.Scale()); // 比例尺 map.addControl(new AMap.ToolBar()); // 工具栏
4.3 添加点标记
在地图上添加点标记4:
javascript
// 添加点标记 function addMarker(lnglat, title, content) { var marker = new AMap.Marker({ position: lnglat, title: title, map: map }); // 添加信息窗口 var infoWindow = new AMap.InfoWindow({ content: content, offset: new AMap.Pixel(0, -30) }); // 点击标记显示信息窗口 marker.on('click', function() { infoWindow.open(map, marker.getPosition()); }); return marker; } // 使用示例 var marker = addMarker([116.480881, 39.989410], '标记标题', '标记内容');
4.4 绘制折线和多边形
在地图上绘制折线和多边形4:
javascript
// 绘制折线 function addPolyline(path, strokeColor, strokeWeight) { var polyline = new AMap.Polyline({ path: path, strokeColor: strokeColor, strokeWeight: strokeWeight, map: map }); return polyline; } // 绘制多边形 function addPolygon(path, strokeColor, fillColor) { var polygon = new AMap.Polygon({ path: path, strokeColor: strokeColor, fillColor: fillColor, map: map }); return polygon; } // 使用示例 var path = [ [116.368904, 39.913423], [116.382122, 39.901176], [116.387271, 39.912501], [116.398258, 39.904600] ]; var polyline = addPolyline(path, "#3366FF", 5);
4.5 地理编码与逆地理编码
JavaScript API也提供了地理编码和逆地理编码的功能10:
javascript
// 地理编码 function geocode(address, city) { return new Promise(function(resolve, reject) { AMap.plugin('AMap.Geocoder', function() { var geocoder = new AMap.Geocoder({ city: city || '' // 城市,默认全国 }); geocoder.getLocation(address, function(status, result) { if (status === 'complete' && result.geocodes.length > 0) { resolve(result.geocodes[0]); } else { reject(status); } }); }); }); } // 逆地理编码 function regeocode(lnglat) { return new Promise(function(resolve, reject) { AMap.plugin('AMap.Geocoder', function() { var geocoder = new AMap.Geocoder(); geocoder.getAddress(lnglat, function(status, result) { if (status === 'complete' && result.regeocode) { resolve(result.regeocode); } else { reject(status); } }); }); }); } // 使用示例 geocode('北京市朝阳区阜通东大街6号').then(function(result) { console.log('地理编码结果:', result); }); regeocode([116.480881, 39.989410]).then(function(result) { console.log('逆地理编码结果:', result); });
5 前后端数据交互
在实际应用中,通常由Python后端处理数据,然后将结果传递给前端JavaScript显示。以下是一种常见的实现方式。
5.1 Python后端(Flask示例)
使用Flask框架创建后端服务:
python
from flask import Flask, jsonify, request, render_template import requests app = Flask(__name__) # 高德API配置 AMAP_API_KEY = '你的Web服务API Key' @app.route('/') def index(): return render_template('map.html') @app.route('/geocode') def geocode(): address = request.args.get('address') city = request.args.get('city', '') url = 'https://restapi.amap.com/v3/geocode/geo' params = { 'key': AMAP_API_KEY, 'address': address, 'city': city, 'output': 'json' } response = requests.get(url, params=params) data = response.json() if data['status'] == '1' and int(data['count']) > 0: location = data['geocodes'][0]['location'] lng, lat = location.split(',') return jsonify({ 'status': 'success', 'lng': float(lng), 'lat': float(lat), 'address': data['geocodes'][0]['formatted_address'] }) else: return jsonify({ 'status': 'error', 'message': '地理编码失败' }) @app.route('/search_around') def search_around(): lng = request.args.get('lng') lat = request.args.get('lat') keywords = request.args.get('keywords', '') radius = request.args.get('radius', 3000, type=int) url = 'https://restapi.amap.com/v3/place/around' params = { 'key': AMAP_API_KEY, 'location': f'{lng},{lat}', 'keywords': keywords, 'radius': radius, 'output': 'json' } response = requests.get(url, params=params) data = response.json() if data['status'] == '1': return jsonify({ 'status': 'success', 'pois': data['pois'] }) else: return jsonify({ 'status': 'error', 'message': '周边搜索失败' }) if __name__ == '__main__': app.run(debug=True)
5.2 前端与后端交互
前端JavaScript通过Ajax调用后端API获取数据:
javascript
// 获取地理编码 function getGeocode(address, city) { return fetch(`/geocode?address=${encodeURIComponent(address)}&city=${encodeURIComponent(city)}`) .then(response => response.json()); } // 获取周边搜索结果 function getAroundSearch(lng, lat, keywords, radius) { return fetch(`/search_around?lng=${lng}&lat=${lat}&keywords=${encodeURIComponent(keywords)}&radius=${radius}`) .then(response => response.json()); } // 使用示例 getGeocode('北京市朝阳区阜通东大街6号').then(data => { if (data.status === 'success') { console.log('经纬度:', data.lng, data.lat); // 在地图上添加标记 addMarker([data.lng, data.lat], data.address, data.address); // 设置地图中心点 map.setCenter([data.lng, data.lat]); } }); // 搜索周边并显示结果 function searchAndShow(lng, lat, keywords) { getAroundSearch(lng, lat, keywords, 1000).then(data => { if (data.status === 'success') { data.pois.forEach(poi => { var location = poi.location.split(','); var lnglat = [parseFloat(location[0]), parseFloat(location[1])]; addMarker(lnglat, poi.name, ` <div> <h3>${poi.name}</h3> <p>地址:${poi.address}</p> <p>类型:${poi.type}</p> <p>距离:${poi.distance}米</p> </div> `); }); } }); }
5.3 完整示例:地址查询与周边搜索
以下是一个完整的示例,实现地址查询和周边搜索功能:
html
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>地图查询示例</title> <style> #map-container { width: 100%; height: 500px; } .controls { margin: 10px 0; padding: 10px; background: #f5f5f5; border-radius: 5px; } input, button { padding: 8px; margin: 5px; } </style> </head> <body> <div class="controls"> <input type="text" id="address-input" placeholder="输入地址"> <input type="text" id="city-input" placeholder="输入城市(可选)"> <button id="geocode-btn">查询地址</button> <input type="text" id="keywords-input" placeholder="搜索关键词"> <button id="search-btn">周边搜索</button> </div> <div id="map-container"></div> <script src="https://webapi.amap.com/maps?v=2.0&key=你的JSAPI_KEY"></script> <script> // 初始化地图 var map = new AMap.Map('map-container', { zoom: 13, center: [116.397428, 39.90923], viewMode: '2D' }); // 添加控件 map.addControl(new AMap.Scale()); map.addControl(new AMap.ToolBar()); // 存储当前中心点标记 var centerMarker = null; // 地理编码查询 document.getElementById('geocode-btn').addEventListener('click', function() { var address = document.getElementById('address-input').value; var city = document.getElementById('city-input').value; if (!address) { alert('请输入地址'); return; } getGeocode(address, city).then(data => { if (data.status === 'success') { // 移除原有标记 if (centerMarker) { map.remove(centerMarker); } // 添加新标记 centerMarker = addMarker([data.lng, data.lat], data.address, data.address); // 设置地图中心 map.setCenter([data.lng, data.lat]); alert('查询成功:' + data.address); } else { alert('查询失败:' + data.message); } }); }); // 周边搜索 document.getElementById('search-btn').addEventListener('click', function() { var center = map.getCenter(); var keywords = document.getElementById('keywords-input').value; if (!keywords) { alert('请输入搜索关键词'); return; } searchAndShow(center.lng, center.lat, keywords); }); // 添加标记函数 function addMarker(lnglat, title, content) { var marker = new AMap.Marker({ position: lnglat, title: title, map: map }); var infoWindow = new AMap.InfoWindow({ content: content, offset: new AMap.Pixel(0, -30) }); marker.on('click', function() { infoWindow.open(map, marker.getPosition()); }); return marker; } // 获取地理编码 function getGeocode(address, city) { return fetch(`/geocode?address=${encodeURIComponent(address)}&city=${encodeURIComponent(city)}`) .then(response => response.json()); } // 周边搜索并显示结果 function searchAndShow(lng, lat, keywords) { // 先清除之前的搜索结果 clearSearchResults(); getAroundSearch(lng, lat, keywords, 1000).then(data => { if (data.status === 'success') { data.pois.forEach(poi => { var location = poi.location.split(','); var lnglat = [parseFloat(location[0]), parseFloat(location[1])]; addMarker(lnglat, poi.name, ` <div> <h3>${poi.name}</h3> <p>地址:${poi.address}</p> <p>类型:${poi.type}</p> <p>距离:${poi.distance}米</p> </div> `); }); alert('找到 ' + data.pois.length + ' 个结果'); } else { alert('搜索失败:' + data.message); } }); } // 获取周边搜索结果 function getAroundSearch(lng, lat, keywords, radius) { return fetch(`/search_around?lng=${lng}&lat=${lat}&keywords=${encodeURIComponent(keywords)}&radius=${radius}`) .then(response => response.json()); } // 清除搜索结果 function clearSearchResults() { // 在实际应用中,需要记录所有搜索结果的标记并移除 // 这里简化处理,只移除不是中心点的标记 if (centerMarker) { map.remove(centerMarker); centerMarker = null; } // 更完整的实现需要维护一个标记列表 } </script> </body> </html>
6 高级功能与优化
6.1 使用WebSocket实时更新位置
对于需要实时更新位置的场景,可以使用WebSocket实现:
python
// 连接WebSocket var socket = io(); // 发送位置更新 function updateLocation(lng, lat) { socket.emit('update_location', { lng: lng, lat: lat, timestamp: Date.now() }); } // 接收位置更新 socket.on('location_updated', function(data) { // 更新地图上的位置标记 updateMarker(data); });
前端代码:
javascript
// 连接WebSocket var socket = io(); // 发送位置更新 function updateLocation(lng, lat) { socket.emit('update_location', { lng: lng, lat: lat, timestamp: Date.now() }); } // 接收位置更新 socket.on('location_updated', function(data) { // 更新地图上的位置标记 updateMarker(data); });
6.2 使用数据库存储位置数据
通常需要将位置数据存储到数据库中,以下是一个使用SQLite的示例:
python
import sqlite3 from datetime import datetime def init_db(): conn = sqlite3.connect('locations.db') c = conn.cursor() c.execute(''' CREATE TABLE IF NOT EXISTS locations (id INTEGER PRIMARY KEY AUTOINCREMENT, lng REAL NOT NULL, lat REAL NOT NULL, address TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP) ''') conn.commit() conn.close() def save_location(lng, lat, address=None): conn = sqlite3.connect('locations.db') c = conn.cursor() c.execute(''' INSERT INTO locations (lng, lat, address) VALUES (?, ?, ?) ''', (lng, lat, address)) conn.commit() conn.close() def get_locations(limit=100): conn = sqlite3.connect('locations.db') c = conn.cursor() c.execute(''' SELECT lng, lat, address, created_at FROM locations ORDER BY created_at DESC LIMIT ? ''', (limit,)) results = c.fetchall() conn.close() return results
6.3 性能优化建议
使用缓存:对于频繁查询的地址,可以使用缓存减少API调用7。
批量处理:当需要处理大量地址时,可以考虑使用批量查询功能(如果API支持)。
错误处理:添加适当的错误处理和重试机制7。
速率限制:遵守高德地图API的调用频率限制7。
7 总结
本文详细介绍了如何使用Python开发调用高德地图API,并在JavaScript网页中显示地图。主要内容包括:
高德地图API的申请和使用:包括Web服务API和JavaScript API。
Python调用高德Web服务API:实现地理编码、逆地理编码、路径规划和周边搜索等功能。
前端JavaScript地图显示:初始化地图、添加标记、绘制图形等。
前后端数据交互:使用Flask框架搭建后端服务,前端通过Ajax调用后端API。
高级功能与优化:使用WebSocket实时更新位置、数据库存储和性能优化。
通过本文的学习,你可以实现一个完整的地图应用,包括地址查询、位置显示、周边搜索等功能。在实际开发中,可以根据需求进一步扩展功能,如路径规划、地理围栏、实时定位等。
7.1 进一步学习资源
到此这篇关于Python调用高德地图API实现JS网页地图显示的文章就介绍到这了,更多相关Python调用高德地图API实现JS网页地图显示内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!