最近公司項目中需要根據兩個地點的交通路徑和距離做一些數據推薦,為了程序的穩定和用戶體驗所以想從百度地圖 API 采集數據保存到數據庫中,經過一翻研究之後選定了百度地圖 Web 服務 API 中的 Direction API ,最後寫了個服務去定時采集。 關於 Direction API 的相關說明這裡不做詳細闡述了,大家可以去百度地圖 API 的頁面去詳細了解,地址:http://developer.baidu.com/map/direction-api.htm。 一、准備工作 1、首先要去申請一個密鑰, 根據自己的需求選擇相應的功能,需要注意的是如果請求校驗方式選擇了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 的方法: 1 /// <summary> 2 /// 發送 API 請求並返回方案信息。 3 /// </summary> 4 /// <returns></returns> 5 private static T RequestApi<T>(string origin, string origin_region, string destination, string destination_region, string mode) 6 { 7 string apiUrl = "http://api.map.baidu.com/direction/v1"; 8 //string ak = "E4805d16520de693a3fe707cdc962045"; 9 string apiKey = "E4805d16520de693a3fe707cdc962045"; // 10 string output = "json"; 11 //string origin_region = "北京"; 12 //string origin = "清華大學"; 13 //string destination = "北京大學"; 14 //string destination_region = "北京"; 15 //string mode = "driving"; 16 IDictionary<string, string> param = new Dictionary<string, string>(); 17 param.Add("ak", apiKey); 18 param.Add("output", output); 19 if (mode == "driving") 20 { 21 param.Add("origin_region", origin_region); 22 param.Add("destination_region", destination_region); 23 } 24 else 25 { 26 param.Add("region", origin_region); 27 } 28 29 param.Add("origin", origin); 30 param.Add("destination", destination); 31 param.Add("mode", mode); 32 33 string result = string.Empty; 34 35 //初始化方案信息實體類。 36 T info = default(T); 37 try 38 { 39 //以 Get 形式請求 Api 地址 40 result = HttpUtils.DoGet(apiUrl, param); 41 info = JsonHelper.FromJsonTo<T>(result); 42 } 43 catch (Exception) 44 { 45 info = default(T); 46 throw; 47 } 48 49 return info; 50 } HttpUtils 類: 查看代碼 1 /// <summary> 2 /// 提供 Http 相關方法。 3 /// </summary> 4 public class HttpUtils 5 { 6 7 /// <summary> 8 /// 執行HTTP GET請求。 9 /// </summary> 10 /// <param name="url">請求地址</param> 11 /// <param name="parameters">請求參數</param> 12 /// <returns>HTTP響應</returns> 13 public static string DoGet(string url, IDictionary<string, string> parameters) 14 { 15 if (parameters != null && parameters.Count > 0) 16 { 17 if (url.Contains("?")) 18 { 19 url = url + "&" + BuildPostData(parameters); 20 } 21 else 22 { 23 url = url + "?" + BuildPostData(parameters); 24 } 25 } 26 27 HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url); 28 req.ServicePoint.Expect100Continue = false; 29 req.Method = "GET"; 30 req.KeepAlive = true; 31 req.UserAgent = "Test"; 32 req.ContentType = "application/x-www-form-urlencoded;charset=utf-8"; 33 34 HttpWebResponse rsp = null; 35 try 36 { 37 rsp = (HttpWebResponse)req.GetResponse(); 38 } 39 catch (WebException webEx) 40 { 41 if (webEx.Status == WebExceptionStatus.Timeout) 42 { 43 rsp = null; 44 } 45 } 46 47 if (rsp != null) 48 { 49 if (rsp.CharacterSet != null) 50 { 51 Encoding encoding = Encoding.GetEncoding(rsp.CharacterSet); 52 return GetResponseAsString(rsp, encoding); 53 } 54 else 55 { 56 return string.Empty; 57 } 58 } 59 else 60 { 61 return string.Empty; 62 } 63 } 64 65 /// <summary> 66 /// 把響應流轉換為文本。 67 /// </summary> 68 /// <param name="rsp">響應流對象</param> 69 /// <param name="encoding">編碼方式</param> 70 /// <returns>響應文本</returns> 71 private static string GetResponseAsString(HttpWebResponse rsp, Encoding encoding) 72 { 73 StringBuilder result = new StringBuilder(); 74 Stream stream = null; 75 StreamReader reader = null; 76 77 try 78 { 79 // 以字符流的方式讀取HTTP響應 80 stream = rsp.GetResponseStream(); 81 reader = new StreamReader(stream, encoding); 82 83 // 每次讀取不大於256個字符,並寫入字符串 84 char[] buffer = new char[256]; 85 int readBytes = 0; 86 while ((readBytes = reader.Read(buffer, 0, buffer.Length)) > 0) 87 { 88 result.Append(buffer, 0, readBytes); 89 } 90 } 91 catch (WebException webEx) 92 { 93 if (webEx.Status == WebExceptionStatus.Timeout) 94 { 95 result = new StringBuilder(); 96 } 97 } 98 finally 99 { 100 // 釋放資源 101 if (reader != null) reader.Close(); 102 if (stream != null) stream.Close(); 103 if (rsp != null) rsp.Close(); 104 } 105 106 return result.ToString(); 107 } 108 109 /// <summary> 110 /// 組裝普通文本請求參數。 111 /// </summary> 112 /// <param name="parameters">Key-Value形式請求參數字典。</param> 113 /// <returns>URL編碼後的請求數據。</returns> 114 private static string BuildPostData(IDictionary<string, string> parameters) 115 { 116 StringBuilder postData = new StringBuilder(); 117 bool hasParam = false; 118 119 IEnumerator<KeyValuePair<string, string>> dem = parameters.GetEnumerator(); 120 while (dem.MoveNext()) 121 { 122 string name = dem.Current.Key; 123 string value = dem.Current.Value; 124 // 忽略參數名或參數值為空的參數 125 if (!string.IsNullOrEmpty(name) && !string.IsNullOrEmpty(value)) 126 { 127 if (hasParam) 128 { 129 postData.Append("&"); 130 } 131 132 postData.Append(name); 133 postData.Append("="); 134 postData.Append(Uri.EscapeDataString(value)); 135 hasParam = true; 136 } 137 } 138 139 return postData.ToString(); 140 } 141 142 } 通過循環調用 RequestApi 的方式就可以獲取兩個地點的交通數據了。 Json 轉換後的實體類可以通過 json2csharp 工具直接生成,地址:http://json2csharp.com/。 二、需要注意的是: 1、這個 API 有時候請求之後響應時間較長,經常會超時,所以我在 HttpUtils 類裡拋出了 WebException 異常。 2、Json 轉換的方法裡也要做異常處理。