分享一套抓數據小程序,客戶資料、實時新聞、股票數據…隨心抓


     為了拓展公司業務,客服部需要大量相關行業的客戶資料。由於公司規模不大,從成本上考慮購買數據不太現實,所以我們就開發了一套方案,從行業相關的商業網站上去抓取客戶資料。

   鑒於不同的網站在數據排版、字符編碼、獲取數據方式(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類提供了各種場景需要的方法,有興趣的可以深入研究。

源碼下載

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM