轉自:http://www.cnblogs.com/TianFang/archive/2013/01/03/2842913.html
這兩天看了下如何獲取天氣預報,寫篇文章總結下:
Weather.com有如下三個Json格式的查詢接口,以北京為例:
直接訪問它就可以獲取到Json格式的數據,解析后就可以用了。其中第三個m.weather.com.cn的信息最全,其它的幾個做一個當天的天氣預報也夠用了。要獲取其它城市的天氣,只需要把標紅的城市ID改成其它ID即可,至于城市的ID如何獲取,下面就簡單的介紹一下。
ID是一個9位的數字,按照長度可以分為如下四部分:
???? 101(國家代號) ? 01(省) ? 01(二級地區) ? 00(三級地區)
其中前面三位國家代號101是固定的,無需獲取。關鍵是獲取后面三級地區編碼代號。要獲取所有的地區代碼,可以通過如下地址獲取:
???? http://m.weather.com.cn/data5/city 0101.xml
它有一個參數,就是地區代號,返回的是下一級的地區代號。另外,雖然它的uri格式是一個xml,實際上返回的可不是xml,而是一個類似" 01|北京,02|上海,03|天津,04|重慶 "的格式化的字符串,不過也很好解析就是啦。
要獲取所有的地區代號,可以通過如下方式:
-
訪問 http://m.weather.com.cn/data5/city.xml 得到所有省的編號(示例:01|北京,02|上海,03|天津)
-
根據省的編號獲取所有二級地區的編號,以北京為例,訪問 http://m.weather.com.cn/data5/city 01.xml 即可。
-
根據二級編號訪問即可獲取三級編號,示例: http://m.weather.com.cn/data5/city 0101.xml 。
有了上述基礎后,我們就可以簡單的寫一個小程序獲取所有城市的ID了
????
class
?
CityInfo
????{
????????
public
?
string
?Name {?
get
;?
private
?
set
; }
????????
public
?
string
?Id {?
get
;?
private
?
set
; }
????????
private
?CityInfo()????????
//
這個對象不能被外部創建
????????{
????????}
????????
public
?
override
?
string
?ToString()
????????{
????????????
return
?
string
.Format(
"[{0}, {1}]"
, Name, Id);
????????}
????????
static
?
HttpClient
?httpClient =?
new
?
HttpClient
();
????????
async
?
Task
<
CityInfo
[]> GetSubCitiesAsync()
????????{
????????????
var
?requestUrl =?
string
.Format(
"http://m.weather.com.cn/data5/city{0}.xml"
, Id);
????????????
var
?result =?
await
?httpClient.GetStringAsync(requestUrl);
????????????
var
?cityInfo =?
from
?city?
in
?result.Split(
','
)
?????????????????????????
let
?data = city.Split(
'|'
)
?????????????????????????
select
?
new
?
CityInfo
() { Id = data[0], Name = data[1] };
????????????
return
?cityInfo.ToArray();
????????}
????????
static
?
async
?
Task
<
IEnumerable
<
CityInfo
>> GetSubCitiesAsync(
IEnumerable
<
CityInfo
> cities)
????????{
????????????
var
?tasks = cities.Select(i => i.GetSubCitiesAsync());
????????????
await
?
Task
.WhenAll(tasks);
????????????
return
?tasks.Select(i => i.Result).SelectMany(i => i);
????????}
????????
public
?
static
?
async
?
Task
<
IEnumerable
<
CityInfo
>> GetAllCitiesAsync()
????????{
????????????
var
?root =?
new
?
CityInfo
();????????
//
空對象
為
0
級對象
????????????
var
?level1Cities =?
await
?root.GetSubCitiesAsync();
????????????
var
?level2Cities =?
await
?GetSubCitiesAsync(level1Cities);
????????????
var
?level3Cities =?
await
?GetSubCitiesAsync(level2Cities);
????????????
return
?level3Cities;
????????}
????}
這個類使用非常簡單,它就只有一個接口 GetAllCitiesAsync() ,通過它可以返回所有三級城市的ID。
????
foreach
?(
var
?item?
in
?
await
?
CityInfo
.GetAllCitiesAsync())
????{
????????
Console
.WriteLine(item);
????}
由于獲取速度主要依賴于網絡,我這里的邏輯做得比較簡單,并沒有刻意追求最高效率。簡單的試了下,大概20s左右能返回結果,總共有2564個城市,這么看來網上的那份城市ID列表是不全的。
關于城市列表,我這里就不貼了,有需要的自己把我上面的代碼運行一下即可(需要.net 4.5環境)。
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
