DotNet 调用百度地图 LBS 服务 API
最近公司项目中需要根据两个地点的交通路径和距离做一些数据推荐,为了程序的稳定和用户体验所以想从百度地图 API 采集数据保存到数据库中,经过一翻研究之后选定了百度地图 Web 服务 API 中的 Direction API ,最后写了个服务去定时采集。
关于 Direction API 的相关说明这里不做详细阐述了,大家可以去百度地图 API 的页面去详细了解,地址:http://developer.baidu.com/map/direction-api.htm。
一、准备工作
1、首先要去申请一个密钥,地址:http://lbsyun.baidu.com/apiconsole/key?application=key
根据自己的需求选择相应的功能,需要注意的是如果请求校验方式选择了sn校验方式的话,在请求 Api 地址的时候需要传入sn参数。
如下图所示:
2、下表是请求接口参数
参数 | 是否必须 | 格式举例 | 参数含义 |
---|---|---|---|
origin | 必选 | 名称:百度大厦 坐标格式为:lat<纬度>,lng<经度> 名称+经纬度:百度大厦|40.056878,116.30815 |
起点名称或经纬度,或者可同时提供名称和经纬度,此时经纬度优先级高,将作为导航依据,名称只负责展示。 |
destination | 必选 | 名称:天安门 经纬度:39.915285, 116.403857 坐标格式为:lat<纬度>,lng<经度> 名称+经纬度:百度大厦|40.056878,116.30815 |
起点名称或经纬度,或者可同时提供名称和经纬度,此时经纬度优先级高,将作为导航依据,名称只负责展示。 |
mode | 选填,默认为driving | driving(驾车模式) | 导航模式,包括:driving(驾车)、walking(步行)、transit(公交) |
region | 必填 | 北京 | 公交、步行导航时该参数必填。 |
origin_region | 必填 | 北京 | 起始点所在城市,驾车导航时必填。 |
destination_region | 必填 | 北京 | 终点所在城市,驾车导航时必填。 |
output | 选填,默认为xml | json | 表示输出类型,可设置为xml或json,默认为xml。 |
coord_type | 选填,默认为bd09ll | gcj02(国测局坐标,如google,soso地图均采用该坐标) | 坐标类型,可选参数,默认为bd09ll。允许的值为:bd09ll(百度经纬度坐标)、bd09mc(百度摩卡托坐标)、gcj02(国测局加密坐标)、wgs84(gps设备获取的坐标)。 |
waypoints | 选填 | 奎科科技大厦|西单 | 途经点集合,包括一个或多个用竖线字符 "|" 分隔的地址名称或经纬度。 |
tactics | 选填 | 11 | 导航策略。导航路线类型,10,不走高速;11、最少时间;12、最短路径。 |
ak | 必填 | E4805d16520de693a3fe707cdc962045 | 用户的访问权限 |
sn | 选填 | 用户的权限签名 | |
timestamp | sn存在时必填 | 时间戳,与sn配合使用。 |
3、通过 GET 请求采集 API 数据
请求 API 的方法:
/// <summary> /// 发送 API 请求并返回方案信息。 /// </summary> /// <returns></returns> private static T RequestApi<T>(string origin, string origin_region, string destination, string destination_region, string mode) { string apiUrl = "http://api.map.baidu.com/direction/v1"; //string ak = "E4805d16520de693a3fe707cdc962045"; string apiKey = "E4805d16520de693a3fe707cdc962045"; // string output = "json"; //string origin_region = "北京"; //string origin = "清华大学"; //string destination = "北京大学"; //string destination_region = "北京"; //string mode = "driving"; IDictionary<string, string> param = new Dictionary<string, string>(); param.Add("ak", apiKey); param.Add("output", output); if (mode == "driving") { param.Add("origin_region", origin_region); param.Add("destination_region", destination_region); } else { param.Add("region", origin_region); } param.Add("origin", origin); param.Add("destination", destination); param.Add("mode", mode); string result = string.Empty; //初始化方案信息实体类。 T info = default(T); try { //以 Get 形式请求 Api 地址 result = HttpUtils.DoGet(apiUrl, param); info = JsonHelper.FromJsonTo<T>(result); } catch (Exception) { info = default(T); throw; } return info; }
HttpUtils 类:
/// <summary> /// 提供 Http 相关方法。 /// </summary> public class HttpUtils { /// <summary> /// 执行HTTP GET请求。 /// </summary> /// <param name="url">请求地址</param> /// <param name="parameters">请求参数</param> /// <returns>HTTP响应</returns> public static string DoGet(string url, IDictionary<string, string> parameters) { if (parameters != null && parameters.Count > 0) { if (url.Contains("?")) { url = url + "&" + BuildPostData(parameters); } else { url = url + "?" + BuildPostData(parameters); } } HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url); req.ServicePoint.Expect100Continue = false; req.Method = "GET"; req.KeepAlive = true; req.UserAgent = "Test"; req.ContentType = "application/x-www-form-urlencoded;charset=utf-8"; HttpWebResponse rsp = null; try { rsp = (HttpWebResponse)req.GetResponse(); } catch (WebException webEx) { if (webEx.Status == WebExceptionStatus.Timeout) { rsp = null; } } if (rsp != null) { if (rsp.CharacterSet != null) { Encoding encoding = Encoding.GetEncoding(rsp.CharacterSet); return GetResponseAsString(rsp, encoding); } else { return string.Empty; } } else { return string.Empty; } } /// <summary> /// 把响应流转换为文本。 /// </summary> /// <param name="rsp">响应流对象</param> /// <param name="encoding">编码方式</param> /// <returns>响应文本</returns> private static string GetResponseAsString(HttpWebResponse rsp, Encoding encoding) { StringBuilder result = new StringBuilder(); Stream stream = null; StreamReader reader = null; try { // 以字符流的方式读取HTTP响应 stream = rsp.GetResponseStream(); reader = new StreamReader(stream, encoding); // 每次读取不大于256个字符,并写入字符串 char[] buffer = new char[256]; int readBytes = 0; while ((readBytes = reader.Read(buffer, 0, buffer.Length)) > 0) { result.Append(buffer, 0, readBytes); } } catch (WebException webEx) { if (webEx.Status == WebExceptionStatus.Timeout) { result = new StringBuilder(); } } finally { // 释放资源 if (reader != null) reader.Close(); if (stream != null) stream.Close(); if (rsp != null) rsp.Close(); } return result.ToString(); } /// <summary> /// 组装普通文本请求参数。 /// </summary> /// <param name="parameters">Key-Value形式请求参数字典。</param> /// <returns>URL编码后的请求数据。</returns> private static string BuildPostData(IDictionary<string, string> parameters) { StringBuilder postData = new StringBuilder(); bool hasParam = false; IEnumerator<KeyValuePair<string, string>> dem = parameters.GetEnumerator(); while (dem.MoveNext()) { string name = dem.Current.Key; string value = dem.Current.Value; // 忽略参数名或参数值为空的参数 if (!string.IsNullOrEmpty(name) && !string.IsNullOrEmpty(value)) { if (hasParam) { postData.Append("&"); } postData.Append(name); postData.Append("="); postData.Append(Uri.EscapeDataString(value)); hasParam = true; } } return postData.ToString(); } }
通过循环调用 RequestApi 的方式就可以获取两个地点的交通数据了。
Json 转换后的实体类可以通过 json2csharp 工具直接生成,地址:http://json2csharp.com/。
二、需要注意的是:
1、这个 API 有时候请求之后响应时间较长,经常会超时,所以我在 HttpUtils 类里抛出了 WebException 异常。
2、Json 转换的方法里也要做异常处理。