天气预报抓取的方法和源代码(包括从IP获取)

  • 天气预报抓取的方法和源代码(包括从IP获取)
  • 作者: 毛虫    文章来源:www.cnblogs.com    发布日期:2009-7-22 11:14:21    浏览次数:1604
  •    前段时间在公司系统(电联协同管理软件)中需要天气预报信息。据此就写了一个天气预报抓取的类。今天说一下我抓取的思路和方法,并共享一下源代码。
      刚开始做的时候,在网上找了一下代码。发现WebXml.com.cn上面有直接可调用的webServices地址为http://webservice.webxml.com.cn/WebServices/WeatherWS.asmx。不过他对免费调用的用户有一定限制,请看http://www.webxml.com.cn/zh_cn/web_services_user.aspx。所以我打算自己写。
      我发现很多网站包括WebXml都是从中国天气网(www.weather.com.cn)抓取的。经过分析,发现可以有2总方法或去数据:
      1.直接掉用它的JS获取数据的方式。
      这种方法获取简单,但数据量不多。
      它本身就一个地址可直接获取JSON数据:http://m.weather.com.cn/data/天气代码.html。获取到的数据如下:

    { " weatherinfo " :{ " city " : " 北京 " , " date_y " : " 2009年7月22日 " , " date " : " 六月初一 " , " week " : " 星期三 " , " fchh " : " 08 " , " cityid " : " 101010100 " , " temp1 " : " 33℃~24℃ " , " temp2 " : " 27℃~20℃ " , " temp3 " : " 31℃~21℃ " , " temp4 " : " 35℃~21℃ " , " weather1 " : " 阴转雷阵雨 " , " weather2 " : " 雷阵雨转阵雨 " , " weather3 " : " 多云 " , " weather4 " : " 晴 " , " img1 " : " 2 " , " img2 " : " 4 " , " img3 " : " 4 " , " img4 " : " 3 " , " img5 " : " 1 " , " img6 " : " 99 " , " img7 " : " 0 " , " img8 " : " 99 " , " img_single " : " 2 " , " img_title1 " : " 阴 " , " img_title2 " : " 雷阵雨 " , " img_title3 " : " 雷阵雨 " , " img_title4 " : " 阵雨 " , " img_title5 " : " 多云 " , " img_title6 " : " 多云 " , " img_title7 " : " 晴 " , " img_title8 " : " 晴 " , " img_title_single " : " 阴 " , " wind1 " : " 微风 " , " wind2 " : " 微风 " , " wind3 " : " 微风 " , " wind4 " : " 微风 " , " fl1 " : " 小于3级 " , " fl2 " : " 小于3级 " , " fl3 " : " 小于3级 " , " fl4 " : " 小于3级 " , " index " : " 炎热 " , " index_d " : " 天气炎热,建议着短衫、短裙、短裤、薄型T恤衫、敞领短袖棉衫等清凉夏季服装。 " , " index_uv " : " 弱 " , " index_xc " : " 不宜 " , " index_tr " : " 较不宜 " , " index_co " : " 较不舒适 " }}


      要获取他,先建立一个实体类WeatherSimpleInfo:

     

    ///   <summary> 简单天气实体 </summary>
         public   class  WeatherSimpleInfo
        {
             ///   <summary> 城市 </summary>
             public   string  city {  get ;  set ; }
             ///   <summary> 时间 </summary>
             public   string  date_y {  get ;  set ; }
             ///   <summary> 农历时间 </summary>
             public   string  date {  get ;  set ; }
             ///   <summary> ID </summary>
             public   string  cityid {  get ;  set ; }
             ///   <summary> 温度 </summary>
             public   string  temp1 {  get ;  set ; }

             public   string  temp2 {  get ;  set ; }
             ///   <summary> 天气 </summary>
             public   string  weather1 {  get ;  set ; }
             public   string  weather2 {  get ;  set ; }
             ///   <summary> 图片 </summary>
             public   string  img1 {  get ;  set ; }
             public   string  img2 {  get ;  set ; }
             public   string  img3 {  get ;  set ; }
             public   string  img4 {  get ;  set ; }
             ///   <summary> 风 </summary>
             public   string  wind1 {  get ;  set ; }
             public   string  wind2 {  get ;  set ; }
             ///   <summary> 穿衣简单指数 </summary>
             public   string  index {  get ;  set ; }
             ///   <summary> 穿衣指数 </summary>
             public   string  index_d {  get ;  set ; }
             ///   <summary> 紫外线简单指数 </summary>
             public   string  index_uv {  get ;  set ; }
             ///   <summary> 洗车简单指数 </summary>
             public   string  index_xc {  get ;  set ; }
             public   string  index_tr {  get ;  set ; }

             public   override   string  ToString()
            {
                var sb  =   new  StringBuilder();
                sb.AppendFormat( " 城市:{0}/r/n " ,  this .city);
                sb.AppendFormat( " 时间:{0}/r/n " ,  this .date_y);
                sb.AppendFormat( " 天气:{0}/r/n " ,  this .weather1);
                sb.AppendFormat( " 温度:{0}/r/n " ,  this .temp1);
                sb.AppendFormat( " 风:{0}/r/n " ,  this .wind1);
                sb.AppendFormat( " 穿衣指数:({0})。{1}/r/n " ,  this .index,  this .index_d);
                sb.AppendFormat( " 紫外线指数:{0}/r/n " ,  this .index_uv);
                sb.AppendFormat( " 洗车指数:{0}/r/n " ,  this .index_xc);
                 return  sb.ToString();
            }
        }

     

     


       抓取类:WeatherSimple: 

     

    ///   <summary> 简单天气预报数据操作(直接从JSON获取) </summary>
      public   class  WeatherSimple
     {
      
       private   const   string  __Url  =   " http://m.weather.com.cn/data/{0}.html " ;
       public  WeatherSimple() { }
       public  WeatherSimpleInfo weatherinfo {  get ;  set ; }
       ///   <summary> 获取简单天气预报 </summary>
       ///   <param name="name"> 城市代码 </param>
       ///   <returns> 天气预报 </returns>
       public   static  WeatherSimpleInfo Get( string  code)
      {
        using (WebClient wc  =   new  WebClient()){
        wc.Encoding  =  Encoding.UTF8;
        var url = string .Format(__Url,code);
         string  str  =  wc.DownloadString(url);
         return  SerializationHelper.JsonDeserialize < WeatherSimple > (str).weatherinfo;
       }
      }
     }

     

     


       2.抓取Html并分析提取数据的方式。
       这种方法获取复杂,但可以获取较多天气数据。
      天气网的http://www.weather.com.cn/html/weather/天气代码.shtml地址可以显示相关地区的天气信息。
      用WebClient抓取数据后提取。很多人提取数据是使用正则表达式的方式,不过本人正则表达式用的比较烂,就选择XML的方式了。
      众所周知,html本身是不标准的xml。不能直接通过XmlDocumentl来读取。这里我借助了SgmlReaderDll。他可以把Html转换成xml。
      转换成功后我们就可以用xpath的方式来提取数据了,更具需求还可以提取不同的天气指数。具体提取请看原代码。
     这样就完成了天气预报的提取。但这还不够,还必须有获取城市代码的方法.
     获取城市代码可以直接使用http://www.weather.com.cn/data/listinfo/city上级城市代码.xml。去获取到的数据如下
     01|北京,02|上海,03|天津,04|重庆,05|黑龙江,06|吉林,07|辽宁
     我们可以通过Split他提取成包括名称和代码的城市数组。
     有了城市代码后我们还需要通过城市名称获取代码的方法,所以我把它的所有城市和代码都下载到WeatherCity.Xml文件内了。见原代码。
      按照公司的需求,还要有通过访问者IP获取天气的功能。这里我就想到了纯真IP库。用它直接获取IP所在的城市,但纯真IP库里面的城市是比较复杂的,他包括县、城市、区、甚至某个网吧的信息。这里我们要分析他,具体代码如下

     

    ///   <summary> 更具IP获取城市代码 </summary>
             ///   <param name="ipDataPath"> IP库地址 </param>
             ///   <param name="ip"> IP地址 </param>
             ///   <returns> 城市代码 </returns>
       public   static   string  GetCityCodeByIp( string  ipDataPath, string  ip){
       IPLocation.IPLocation.IPLocate(ipDataPath,ip);
       var country  =  IPLocation.IPLocation.Country;
       var regex  =   new  Regex( " ([^市省]+)市 " );
       var match = regex.Match(country);
       var area = string .Empty;
       var province  =   string .Empty;
       var city  =   string .Empty;
       var matCity  =  Regex.Matches(country,  " ([^市省]+)市 " );
       var matArea  =  Regex.Matches(country,  " ([^市省区]+)区 " );
       var matProvince  =  Regex.Matches(country,  " ([^省]+)省 " );
        if (matArea.Count > 0 ){
        area  =  matArea[ 0 ].Result( " $1 " );
       }
        if  (matProvince.Count  >   0 )
       {
        province  =  matProvince[ 0 ].Result( " $1 " );
       }
        if  (matCity.Count  >   0 )
       {
        city  =  matCity[matCity.Count  -   1 ].Result( " $1 " );
       }
       var code = string .Empty;
        if  ( ! string .IsNullOrEmpty(area))
       {
        code  =  GetCityCodeByName(area);
         if  ( ! string .IsNullOrEmpty(code))
        {
          return  code;
        }
       }
        if  ( ! string .IsNullOrEmpty(city))
       {
        code  =  GetCityCodeByName(city);
         if  ( ! string .IsNullOrEmpty(code))
        {
          return  code;
        }
       }
        if  ( ! string .IsNullOrEmpty(province))
       {
        code  =  GetCityCodeByName(province);
         if  ( ! string .IsNullOrEmpty(code))
        {
          return  code;
        }
       }
        if  ( string .IsNullOrEmpty(code)){
        code  =  GetCityCodeByName(country.Substring( 0 ,  2 ));
         if  ( ! string .IsNullOrEmpty(code))
        {
          return  code;
        }
       }
        return   string .Empty;
      }

     

     

     如此整个天气预报获取就完成了,请下载代码Flashado.Weather.WInForm工程是测试程序,下载后大家可直接用它测试。

     天气预报源代码 http://www.dyinfor.com/files/Flashado.Weather.rar

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值