好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

抓数据小程序

抓数据小程序

  为了拓展公司业务,客服部需要大量相关行业的客户资料。由于公司规模不大,从成本上考虑够买数据不太现实,所以我们就开发了一套方案,从行业相关的商业网站上去抓取客户资料。

   鉴于不同的网站在数据排版、字符编码、获取数据方式(get或post)不同。如要抓到自己想要的数据,针对每个网站都需要进行网页的分析,有效数据的提取。在这里主要分享关键代码,顺便把最近写的一个程序源代码贴出来供园友们下载研究,里面有抓取三个网站数据的例子( 深市A股、三星手机、当当网微软技术丛书,抓取不同的网站需要修改运行入口 )。 掌握其中一个的技巧,便可以在所有类似网站上获取你想要的数据,比方你在炒股,你可以抓取股票网站数据到本地,做个报表分析,操作的好,能让你赚的盆满钵满;假若你自己有个淘宝网店,需要商品图片,copy别人店铺的图片多慢啊,抓取便是;如果你有博客或新闻网站,没有更新的数据怎么办,看中哪个网站抓取便是。 说了这么多,回正题……

下面我以抓取其中一个网站为例来介绍这个小程序,首先抓取任务如下:

http://detail.zol.com.cn/cell_phone_index/subcate57_98_list_1.html
只要图片,手机名称,价格,网络模式,网络类型,其它信息不要
手机图片要下载下来

1.程序界面设计如下,只为达到抓取数据目的,界面比较鄙陋筒靴们将就看:-)。

2.用时信息通过Timer控件的tick事件来显示抓取用的时间,代码如下:

  1    #region   //  时间处理 
  2           int  duration =  0  ;
   3           private   void  timer1_Tick( object   sender, EventArgs e)
   4           {
   5              duration++ ;
   6              lbTime.Text =  "  用时:  "  + GetTimeBySecount( int  .Parse(duration.ToString().Trim()));
   7           }
   8           ///   <summary> 
  9           ///   通过秒返回时:分:秒格式的时间
  10           ///   </summary> 
 11           ///   <returns></returns> 
 12           private   string  GetTimeBySecount( int   s)
  13           {
  14              s = s +  1  ;
  15              TimeSpan timeSpan =  new  TimeSpan( 0 ,  0  , s);
  16               string  hour = timeSpan.Hours <  10  ? timeSpan.Hours.ToString().Trim().PadLeft( 2 ,  '  0  '  ) : timeSpan.Hours.ToString().Trim();
  17               string  minute = timeSpan.Minutes <  10  ? timeSpan.Minutes.ToString().Trim().PadLeft( 2 ,  '  0  '  ) : timeSpan.Minutes.ToString().Trim();
  18               string  second = timeSpan.Seconds <  10  ? timeSpan.Seconds.ToString().Trim().PadLeft( 2 ,  '  0  '  ) : timeSpan.Seconds.ToString().Trim();
  19               return   string .Format( "  {0}:{1}:{2}  "  , hour, minute, second);
  20           }
  21           #endregion 


3.进度信息用的是委托显示抓取详情,代码如下:

  1    #region   //  委托显示用户提示信息 
  2           ///   <summary> 
  3           ///   为了进程之间通信,定义一个委托
   4           ///   </summary> 
  5           ///   <param name="displayString">  实时处理的信息  </param> 
  6           ///   <param name="lbl">  接收实时处理信息的 Label 对象  </param> 
  7           ///   <param name="ui">  承载 Label 控件的窗体对象  </param> 
  8           delegate   void  SetText( string   displayString, Label lbl, Form ui);
   9           ///   <summary> 
 10           ///   利用委托操作窗体线程上的 Lable 控件
  11           ///   </summary> 
 12           ///   <param name="str">  实时处理的信息  </param> 
 13           ///   <param name="lb">  接收实时处理信息的 Label 对象  </param> 
 14           ///   <param name="fui">  承载 Label 控件的窗体对象  </param> 
 15           public   static   void  SetLableText( string   str, Label lb, Form fui)
  16           {
  17               if   (lb.InvokeRequired)
  18               {
  19                  SetText st =  new   SetText(SetLableText);
  20                   fui.Invoke(st, str, lb, fui);
  21               }
  22               else 
 23               {
  24                  lb.Text =  str;
  25               }
  26           }
  27           #endregion 


4.拖放一个backgroundWorker控件,启动DoWork事件和RunWorkerCompleted事件。

DoWork代码如下(代码中标红的方法是几个关键的方法
 Common.Get_HttpAll:根据网页地址,和字符编码获取网页源代码返回string 
 Common.ResolverAndOutput:从网页内容中获取关键信息,通常用于获取列表数据,table里面的tr数据。
参数1传入要分析的网页内容;
参数2传入要分析的网页内容的起始点,为空则表示从网页内容起始位置开始;
参数3传入要分析的网页内容的终结点,为空则表示截止到网页内容的最后位置;
参数4传入过滤规则,例如:<tr>(?<content>.+?)</tr>,表示获取参数2和参数3之间的字符串中所有<tr>开始,</tr>结束的所有字符串,这些字符串用$~拼接;
参数5默认传入1;
参数6默认传入false;
 Common.JieQuString:截取字符串中A和B之间的数据。参数1传入带分析的字符串;参数2传入A(A在字符串中唯一);参数3传入B(B在字符串中唯一) 
):

  1   private   void  backgroundWorker1_DoWork( object   sender, DoWorkEventArgs e)
   2           {
   3               try 
  4               {
   5                  DataSet ds =  new   DataSet();
   6                  DataTable dtContact =  new  DataTable( "  tbl  "  );
   7                  dtContact.Columns.Add( "  name  "  );
   8                  dtContact.Columns.Add( "  price  "  );
   9                  dtContact.Columns.Add( "  fileName  "  );
  10                  dtContact.Columns.Add( "  model  "  );
  11                  dtContact.Columns.Add( "  type  "  );
  12                   DataRow dr;
  13                   int  i =  1  ;
  14                   bool  flag =  true  ;
  15                   do 
 16                   {
  17                       string  path =  "  http://detail.zol.com.cn/cell_phone_index/subcate57_98_list_  "  + i.ToString() +  "  .html  "  ;
  18                       string  getHtml =  Common.Get_HttpAll (path,  "  GB2312  "  );
  19                       if  (!getHtml.Contains( "  wrong  "  ))
  20                       {
  21                           string  useHtml =  Common.ResolverAndOutput (getHtml,  "" ,  "" ,  "  <div class=\"list-item clearfix\">(?<content>.+?)target=\"_blank\">查询底价</a>  " ,  1 ,  false  );
  22                           string [] trItem = useHtml.Replace( "  ~  " ,  "" ).Split( '  $  '  );
  23                          flag = trItem.Length >  2  ;
  24                           for  ( int  j =  0 ; j < trItem.Length -  1 ; j++ )
  25                           {
  26                              SetLableText( "  进度:当前正在分析第  "  + i +  "   页,第  " +(j+ 1 )+ "  条数据  " , lbJD,  this  );
  27                              dr =  dtContact.NewRow();
  28                               string  imgUrl =  Common.JieQuString (trItem[j],  "  <div class=\"pic-box SP\" data-rel=\"  " ,  "  \">  "  );
  29                               int  splitIndex=imgUrl.LastIndexOf( '  /  '  );
  30                               if  (splitIndex <  0  ) {
  31                                   break  ;
  32                               }
  33                               string  fileName= imgUrl.Substring(splitIndex, imgUrl.Length - splitIndex).Replace( "  /  " , ""  );
  34                               //  下载当前产品图片 
 35                               string  filepath =  "  E:\\抓数据\\中关村三星手机图片\\  " + fileName;
  36                              WebClient mywebclient =  new   WebClient();
  37                               mywebclient.DownloadFile(imgUrl, filepath);
  38                               //  填充行值 
 39                              dr[ "  name  " ] = Common.JieQuString(Common.JieQuString(trItem[j],  "  <h3>  " ,  "  </h3>  " ),  "  >  " ,  "  </a>  "  );
  40                              dr[ "  price  " ] = Common.JieQuString(trItem[j], "  <span class=\"price\">¥<b class=''>  " , "  </b></span>  "  );
  41                              dr[ "  fileName  " ] =  fileName;
  42                              dr[ "  model  " ] = Common.JieQuString(trItem[j],  "  <span>网络模式:</span>  " ,  "  </li>  "  );
  43                              dr[ "  type  " ] = Common.JieQuString(trItem[j],  "  <span>网络类型:</span>  " ,  "  </li>  "  );
  44                               dtContact.Rows.Add(dr);
  45                           }
  46                           ds.Tables.Add(dtContact.Copy());
  47                           string  savePath =  "  E:\\抓数据\\中关村三星手机.xml  "  ;
  48                           ds.WriteXml(savePath);
  49                           ds.Tables.Clear();
  50                       }
  51                       else 
 52                       {
  53                           continue  ;
  54                       }
  55                      i++ ;
  56                  }  while   (flag);
  57               }
  58               catch   (Exception ex)
  59               {
  60                  MessageBox.Show( "  代码异常:  "  +  ex);
  61               }
  62          }

RunWorkerCompleted代码如下:

 1   private   void  backgroundWorker1_RunWorkerCompleted( object   sender, RunWorkerCompletedEventArgs e)
  2           {
  3               timer1.Stop();
  4              timer1.Enabled =  false  ;
  5              MessageBox.Show( "  ok,见 E:\\抓数据\\中关村三星手机.xml  "  );
  6          }


5.点击窗体抓取数据启动Click事件,代码如下:

 1   private   void  btnGetData_Click( object   sender, EventArgs e)
  2           {
  3              timer1.Enabled =  true  ;
  4               timer1.Start();
  5               backgroundWorker1.RunWorkerAsync();
  6          }


6.大功告成。启动程序效果如下:

7.运行完成后查看抓取的数据信息和手机图片如下(把Xml文件拖到Excel中显示):

总结:此例只是针对Get请求数据的情况,而且当前抓取的网站都是不需要登录的。而在实际生产中肯定有Post请求数据的,也有需要登录的,源码里面的Common类提供了各种场景需要的方法,有兴趣的可以深入研究。

源码下载

正在看本人博客的这位童鞋,我看你气度不凡,谈吐间隐隐有王者之气,日后必有一番作为!旁边有“推荐”二字,你就顺手把它点了吧,相得准,我分文不收;相不准,你也好回来找我!

 

 

 

标签:  分享

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于抓数据小程序的详细内容...

  阅读:66次