前言:
天氣預報,回憶中做過那麼三次。
第一次的做法是:
技術總監寫了個采集背景,每天早晚各采一次,從tq121站裡采集大量的天氣資訊到資料庫,我就直接從資料庫裡讀資料了。
總結:
這種做法很麻煩,每天要開背景采資料,做成自動的,還要不半路程式自動死亡才行,而且資料庫會産生大堆垃圾過時的資料。
優點是:可以采集很多資訊,做成很專業的天氣預報站,那時候做旅遊站,天氣也是重要子產品,是以這種方式也很合适。
第二次:
自己做畢業設計,都沒采集背景,自己又寫不出采集來,沒資料讀了,隻好到處百度搜尋“天氣預報webservice"調用。
這種做法也很郁悶,首先webservice不好找,第二找到的如果小站提供的,随時又會挂掉了,要是人家挂掉,你要另找一個?
優點是:找到就調用,什麼也不用管,菜鳥也能飛。
第三次:
是電子商務平台在首頁顯示下天氣,那時候正巧遇到剛做完web版的采集系統,于是順理直接使用采集類庫現采現顯。
優點是:不用和資料庫打交道,現采現顯,減少資料庫壓力,速度快,每天隻采一次,丁點資訊,緩存即可。對于天氣隻是裝飾性的極适用。
缺點是:資料量少,不能做能專業性天氣預報站。
以下介紹現采現顯的實作方式
1:既然要采,當然找到有天氣預報的站了,這個很好找,網上到處都是資源,隻要你會采。
比如百度,你搜尋城市如廣州,即會出現天氣資訊了,如圖:
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiInBnauEzXyVGa0FWZ3JXZoRXYn9CXwEDMxAjMvwlM2ETMxl3YvwVbvN2Xzd2bsJmbj9CXt92YuM3ZvxmYuNmLzV2Zh1Wavw1LcpDc0RHaiojIsJye.jpg)
比如騰訊soso,如下圖。當然還有其它很多很多,隻要看得到的,都可以采,不過最好找大站,穩定。
2:采集類,一個好的采集類,事半功倍,以下出一個簡化版,足夠采集天氣資訊
using system;
using system.text;
using system.net;
using system.text.regularexpressions;
namespace cyq.tool
{
/// <summary>
/// 作者:路過秋天
/// 部落格:http://cyq1162.cnblogs.com
/// </summary>
public class gatherhelper
{
/// <summary>
/// 傳回擷取的目标位址html全部代碼
/// </summary>
/// <param name="strurl">目标位址</param>
/// <returns></returns>
public static string gethtmlcode(string pageurl, encoding encoding)
{
try
{
//傳回目标頁html代碼
webclient webclient = new webclient();
webclient.credentials = credentialcache.defaultcredentials;
byte[] buffer = webclient.downloaddata(pageurl);
string htmlcode = encoding.getstring(buffer);
webclient.dispose(); //釋放webclient資源
return htmlcode;
}
catch
return string.empty;
}
#region 内容截取分析
/// 傳回根據内容開始及結束代碼分析出内容
/// <param name="contentcode">内容代碼</param>
/// <param name="startcode">内容所在開始代碼</param>
/// <param name="endcode">内容所在結束代碼</param>
/// <param name="index">取第幾條[從1開始]</param>
public static string getcontent(string contentcode, string startcode, string endcode, int index)
string[] matchitems = null;
return getcontent(contentcode, startcode, endcode, index, out matchitems);
public static string getcontent(string contentcode, string startcode, string endcode, int index, out string[] matchitems)
matchitems = null;
if (string.isnullorempty(startcode) && string.isnullorempty(endcode))
return contentcode;
regex regobj = new regex(startcode + @"([\s\s]*?)" + endcode, regexoptions.compiled | regexoptions.ignorecase);
matchcollection matchitemlist = regobj.matches(contentcode);
if (matchitemlist != null && matchitemlist.count >= index)
matchitems = new string[matchitemlist.count];
for (int i = 0; i < matchitemlist.count; i++)
{
matchitems[i] = matchitemlist[i].groups[1].value;
}
index = index > 0 ? index - 1 : 0;
return matchitemlist[index].groups[1].value;
return string.empty;
#endregion
}
}
3:編寫天氣預報實體類,将采集的資訊以實體傳回,如果采集多個,傳回就是list<實體>了
public class weatherinfo
private string imgurl;
/// 天氣圖檔位址
public string imgurl
get { return imgurl; }
set { imgurl = value; }
private string wind;
/// 天氣風力
public string wind
get { return wind; }
set { wind = value; }
private string cityname;
/// 天氣城市名稱
public string cityname
get { return cityname; }
set { cityname = value; }
private string temperature;
/// 天氣溫度
public string temperature
get { return temperature; }
set { temperature = value; }
private string description;
/// 天氣說明
public string description
get { return description; }
set { description = value; }
4:編寫采集soso的天氣預報類
a:建立采集天氣預報類:weathersearch
public class weathersearch
/// 資料采集來源于騰信搜搜天氣預報
/// <param name="cityname"></param>
public static weatherinfo get(string cityname)
//待實作
private static weatherinfo getformcache(string cityname,string key)
object weather = httpcontext.current.cache.get(key);
if (weather!=null)
return weather as weatherinfo;
return null;
重要說明:
采集一次後,記得緩存起來,不然每次通路都現采,刷刷就被soso給封了,切身經曆啊。
b:get函數分解:
1:先讀取緩存,注意緩存key用日期做key,可以友善緩存今天和删除昨天的緩存。
public static weatherinfo get(string cityname)//中文城市名稱
if (string.isnullorempty(cityname))
return null;
string todaykey = cityname + datetime.now.tostring("yyyymmdd");
weatherinfo weather = getformcache(cityname, todaykey);
if (weather == null)
//待實作
2:讀不到緩存就現采了,調用采集類
if (weather == null)
{
weather = new weatherinfo();
weather.cityname = cityname;
cityname = system.web.httputility.urlencode(cityname + "天氣", encoding.getencoding("gb2312"));
string url = "http://www.soso.com/q?num=1&w=" + cityname;
//采集所有html
string html = gatherhelper.gethtmlcode(url, encoding.getencoding("gb2312"));
//接下來待實作
}
說明:
這裡城市要用中文編碼傳過去,至于url,是我發現的最簡潔的參數,現在已把搜搜的搜尋頁面的全html抓回來了,接下來就是分離出想要的資訊。
3:分析html,縮小範圍,對于一大堆html,我們隻要這一部分
<!--上面的被省略-->
<div class="w_main">
<ol>
<li class="w_space" title="北風4-5級"><span>今天(周五)</span>
<img src="http://cache.soso.com/zdq/wea/s_a3.png" onload="setpng(this,48,48)" />
<span>21 / 28<em>&deg;</em>c</span><span class="w_w">多雲轉陣雨</span> </li>
<li title="北風3-4級"><span>明天(周六)</span>
<span>22 / 28<em>&deg;</em>c</span><span class="w_w">多雲轉陣雨</span> </li>
<li title="微風"><span>後天(周日)</span>
<img src="http://cache.soso.com/zdq/wea/s_a33.png" onload="setpng(this,48,48)" />
<span>18 / 29<em>&deg;</em>c</span><span class="w_w">多雲</span> </li>
</ol>
</div>
<!--下面的也被省略-->
我們使用getcontent方法可以非常友善的縮小範圍,隻要找到唯一的起始标簽和結束标簽,不會正則,也一樣截取。
4:使用getcontent步步截取所需要資訊
if (string.isnullorempty(html)) { return null; }
//縮小範圍
html = gatherhelper.getcontent(html, "<div class=\"w_main\">", "</div>", 1);
if (string.isnullorempty(html)) { return null; }
//說明
weather.description = gatherhelper.getcontent(html, "<span class=\"w_w\">", "</span>", 1);
//圖檔
weather.imgurl = gatherhelper.getcontent(html, "<img src=\"", "\"", 1);
//風向
weather.wind=gatherhelper.getcontent(html, "title=\"", "\"", 1);
//溫度
weather.temperature = gatherhelper.getcontent(html, "/> <span>", "<em>", 1);
5:存入緩存并清除昨天的緩存資訊[看需要展示幾天的資訊了]
httpcontext.current.cache.insert(todaykey, weather);
string yesterdaykey = cityname + datetime.now.adddays(-1).tostring("yyyymmdd");
if (httpcontext.current.cache.get(yesterdaykey)!=null)
httpcontext.current.cache.remove(yesterdaykey);
5:界面調用
protected void page_load(object sender, eventargs e)
weatherinfo info = weathersearch.get("廣州");
if (info != null)
litcity.text = info.cityname;
litdescprtion.text = info.description;
imgurl.imageurl = info.imgurl;
litwind.text = info.wind;
littemperature.text=info.temperature;
6:調用結果
最後結言:
本博沒有快速評論通道,大夥積極點下手。
再不濟手動複制-》“此文不錯,值的推薦”!!
-_-...!!!
ie6好卡,滑鼠又發神經,單擊輕按兩下混在一起,本文寫起來好辛苦~~