使用高德API获取线路数据,无需代码

发布时间 2024-01-07 17:34:19作者: sheyueyu

下面内容包括:

  1. 如何使用高德API获取线路数据,无需代码
  2. 如何将获取下来的线路数据处理成geodataframe

线路数据获取

  • 网址(高德开放平台): https://lbs.amap.com/demo/javascript-api/example/bus-info/search-bus-route
  • 打开网址后替换右侧的js代码(放在了文章的最后)
    • 替换数据: 1. 城市(js代码修改) 2. 线路(直接在面板输入)
  • 点击运行js代码(一定要点击运行,有个运行按钮),在中间的地图组件中会呈现查询到的线路,并会弹出"保存文件”,在此修改文件名,文件为json格式

线路数据处理

  • 上面的数据都是一条一条线路获取的,将其全部放在同一个文件夹
  • python代码处理
import json
import geopandas as gpd
from shapely.geometry import LineString
import glob
import math
# 读取 JSON 文件
# 获取当前目录下所有的 JSON 文件
json_files = glob.glob('./data/*.json')

# 高德gcj-02 转4326
# 公交坐标数据转化
x_pi = 3.14159265358979324 * 3000.0 / 180.0
pi = 3.1415926535897932384626  # π
a = 6378245.0  # 长半轴
ee = 0.00669342162296594323  # 扁率
 
def gcj02towgs84(lng, lat):
    """
    GCJ02(火星坐标系)转GPS84
    :param lng:火星坐标系的经度
    :param lat:火星坐标系纬度
    :return:
    """
    if out_of_china(lng, lat):
        return lng, lat
    dlat = transformlat(lng - 105.0, lat - 35.0)
    dlng = transformlng(lng - 105.0, lat - 35.0)
    radlat = lat / 180.0 * pi
    magic = math.sin(radlat)
    magic = 1 - ee * magic * magic
    sqrtmagic = math.sqrt(magic)
    dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * pi)
    dlng = (dlng * 180.0) / (a / sqrtmagic * math.cos(radlat) * pi)
    mglat = lat + dlat
    mglng = lng + dlng
    return [lng * 2 - mglng, lat * 2 - mglat]

def transformlat(lng, lat):
    ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + 0.1 * lng * lat + 0.2 * math.sqrt(math.fabs(lng))
    ret += (20.0 * math.sin(6.0 * lng * pi) + 20.0 * math.sin(2.0 * lng * pi)) * 2.0 / 3.0
    ret += (20.0 * math.sin(lat * pi) + 40.0 * math.sin(lat / 3.0 * pi)) * 2.0 / 3.0
    ret += (160.0 * math.sin(lat / 12.0 * pi) + 320 * math.sin(lat * pi / 30.0)) * 2.0 / 3.0
    return ret
 
def transformlng(lng, lat):
    ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + 0.1 * lng * lat + 0.1 * math.sqrt(math.fabs(lng))
    ret += (20.0 * math.sin(6.0 * lng * pi) + 20.0 * math.sin(2.0 * lng * pi)) * 2.0 / 3.0
    ret += (20.0 * math.sin(lng * pi) + 40.0 * math.sin(lng / 3.0 * pi)) * 2.0 / 3.0
    ret += (150.0 * math.sin(lng / 12.0 * pi) + 300.0 * math.sin(lng / 30.0 * pi)) * 2.0 / 3.0
    return ret

def out_of_china(lng, lat):
    """
    判断是否在国内,不在国内不做偏移
    :param lng:
    :param lat:
    :return:
    """
    if lng < 72.004 or lng > 137.8347:
        return True
    if lat < 0.8293 or lat > 55.8271:
        return True
    return False

def coordinates(c):
    lng,lat = c.split(',')
    lng,lat = float(lng),float(lat)
    wlng,wlat = gcj02towgs84(lng,lat)
    return wlng,wlat
# 使用示例
gcj02_lng, gcj02_lat = 116.481499, 39.990475  # 示例GCJ-02坐标
wgs84_lng, wgs84_lat = gcj02towgs84(gcj02_lng, gcj02_lat)
print(f"WGS 84坐标:经度={wgs84_lng}, 纬度={wgs84_lat}")


# 数据处理
# 准备用于构建 GeoDataFrame 的数据
gdf_data = []

for file_path in json_files:
    with open(file_path, 'r') as file:
        # 解析 JSON 文件
        json_list = json.load(file)
        # 遍历列表中的每个字典元素
        for json_data in json_list:
            if 'path' in json_data:  # 检查每个字典元素中是否有 'path' 键
                line_coords = [gcj02towgs84(point['lng'], point['lat']) for point in json_data['path']]
                # line_string = LineString(line_coords)
                # line_coords = [(point['lng'], point['lat']) for point in json_data['path']]
                line_string = LineString(line_coords)
                
                gdf_data.append({
                    'id': json_data.get('id', ''),
                    'type': json_data.get('type', ''),
                    'name': json_data.get('name', ''),
                    'geometry': line_string
                })

# 创建 GeoDataFrame
gdf = gpd.GeoDataFrame(gdf_data, crs='EPSG:4326')
# 显示 GeoDataFrame
gdf.plot()
gdf.to_file('./公交线路json/101-102-103_line.geojson',driver='GeoJSON',encoding='utf-8')


<!doctype html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">
    <title>公交线路查询</title>
    <link rel="stylesheet" href="https://a.amap.com/jsapi_demos/static/demo-center/css/demo-center.css"/> 
    <style type="text/css">
       html,body,#container{
           height:100%;
       }
    </style>
</head>
<body>
<div id="container"></div>
<div class="input-card" style='width:18rem;'>
    <label style='color:grey'>公交线路查询</label>
    <div class="input-item">
            <div class="input-item-prepend"><span class="input-item-text" >线路名称</span></div>
            <input id='BusLineName' type="text" value='101' >
    </div>
    <input id="search" type="button" class="btn" value="查询" />
</div>

<script type="text/javascript"
            src="https://webapi.amap.com/maps?v=1.4.15&key=您申请的key值&plugin=AMap.LineSearch"></script>
<script language="javascript">
    /*
     * 该示例主要流程分为三个步骤
     * 1. 首先调用公交路线查询服务(lineSearch)
     * 2. 根据返回结果解析,输出解析结果(lineSearch_Callback)
     * 3. 在地图上绘制公交线路()
     */
    var map = new AMap.Map("container", {
        resizeEnable: true,
        center: [116.397428, 39.90923],//地图中心点
        zoom: 13 //地图显示的缩放级别
    });
    var linesearch;
    /*公交线路查询*/
    function lineSearch() {
        var busLineName = document.getElementById('BusLineName').value;
        if(!busLineName) return;
        //实例化公交线路查询类,只取回一条路线
        
        linesearch = new AMap.LineSearch({
            pageIndex: 1,
            city: '宿迁',
            pageSize: 2,
            extensions: 'all'
        });
        
        //搜索“536”相关公交线路
        linesearch.search(busLineName, function(status, result) {
            map.clearMap()
            if (status === 'complete' && result.info === 'OK') {
                lineSearch_Callback(result);
            } else {
                alert(result);
            }
        });
    }
    /*公交路线查询服务返回数据解析概况*/
/*公交路线查询服务返回数据解析概况*/
function lineSearch_Callback(data) {
    var lineArr = data.lineInfo;
    var lineNum = data.lineInfo.length;
    if (lineNum == 0) {
        alert("未找到相关线路信息。");
    } else {
        for (var i = 0; i < lineNum; i++) {
            var pathArr = lineArr[i].path;
            var stops = lineArr[i].via_stops;
            var startPot = stops[0].location;
            var endPot = stops[stops.length - 1].location;
            if (i == 0) { // 作为示例,只绘制一条线路
                drawbusLine(startPot, endPot, pathArr);
            }
        }
        // 下载查询到的公交线路数据
        download(JSON.stringify(lineArr, null, 4), 'busLineData.json', 'application/json');
    }
}

    /*绘制路线*/
    function drawbusLine(startPot, endPot, BusArr) {
        //绘制起点,终点
        new AMap.Marker({
            map: map,
            position: startPot, //基点位置
            icon: "https://webapi.amap.com/theme/v1.3/markers/n/start.png",
            zIndex: 10
        });
        new AMap.Marker({
            map: map,
            position: endPot, //基点位置
            icon: "https://webapi.amap.com/theme/v1.3/markers/n/end.png",
            zIndex: 10
        });
        //绘制乘车的路线
        busPolyline = new AMap.Polyline({
            map: map,
            path: BusArr,
            
            strokeColor: "#09f",//线颜色
            strokeOpacity: 0.8,//线透明度
            isOutline:true,
            outlineColor:'white',
            strokeWeight: 6//线宽
        });
        map.setFitView();
    }
    lineSearch();
    document.getElementById('search').onclick = lineSearch;
  function download(data, filename, type) {
    var file = new Blob([data], {type: type});
    if (window.navigator.msSaveOrOpenBlob) {
        // IE10+
        window.navigator.msSaveOrOpenBlob(file, filename);
    } else {
        // Others
        var a = document.createElement("a"),
                url = URL.createObjectURL(file);
        a.href = url;
        a.download = filename;
        document.body.appendChild(a);
        a.click();
        setTimeout(function() {
            document.body.removeChild(a);
            window.URL.revokeObjectURL(url);  
        }, 0); 
    }
}
  
</script>
</body>
</html>