天天看點

實戰系列之天氣預報實時采集

前言:

天氣預報,回憶中做過那麼三次。

第一次的做法是:

技術總監寫了個采集背景,每天早晚各采一次,從tq121站裡采集大量的天氣資訊到資料庫,我就直接從資料庫裡讀資料了。

總結:

這種做法很麻煩,每天要開背景采資料,做成自動的,還要不半路程式自動死亡才行,而且資料庫會産生大堆垃圾過時的資料。

優點是:可以采集很多資訊,做成很專業的天氣預報站,那時候做旅遊站,天氣也是重要子產品,是以這種方式也很合适。

第二次:

自己做畢業設計,都沒采集背景,自己又寫不出采集來,沒資料讀了,隻好到處百度搜尋“天氣預報webservice"調用。

這種做法也很郁悶,首先webservice不好找,第二找到的如果小站提供的,随時又會挂掉了,要是人家挂掉,你要另找一個?

優點是:找到就調用,什麼也不用管,菜鳥也能飛。

第三次:

是電子商務平台在首頁顯示下天氣,那時候正巧遇到剛做完web版的采集系統,于是順理直接使用采集類庫現采現顯。

優點是:不用和資料庫打交道,現采現顯,減少資料庫壓力,速度快,每天隻采一次,丁點資訊,緩存即可。對于天氣隻是裝飾性的極适用。

缺點是:資料量少,不能做能專業性天氣預報站。

以下介紹現采現顯的實作方式

1:既然要采,當然找到有天氣預報的站了,這個很好找,網上到處都是資源,隻要你會采。

比如百度,你搜尋城市如廣州,即會出現天氣資訊了,如圖:

實戰系列之天氣預報實時采集

比如騰訊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>°</em>c</span><span class="w_w">多雲轉陣雨</span> </li>

                                                <li title="北風3-4級"><span>明天(周六)</span>

                                                    <span>22 / 28<em>°</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>°</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好卡,滑鼠又發神經,單擊輕按兩下混在一起,本文寫起來好辛苦~~

實戰系列之天氣預報實時采集