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 转换的方法里也要做异常处理。

posted @ 2014-04-09 16:11  Charles Zhang  阅读(19081)  评论(2编辑  收藏  举报