异步网络编程之图片批量抓取下载(C#)

支持

    MSDN上 异步网络编程的例子是我0.2版的核心所在

运行环境

    .NET Framework2.0

开发工具

    Microsoft Visual Studio 2005

正题

    一.    先贴一张图,这个界面就是程序的主界面了:

    

    二.    部分代码说明(主要讲解异步分析和下载):

          异步分析下载采取的策略是同时分析同时下载,即未等待数据全部分析完毕就开始把已经分析出来的图片链接开始下载。下载成功的均在List框链接前面划上了√ ,未能下载的图片有可能是分析错误或者是下载异常。

        1.    异步分析部分代码
  1.         /// <summary>
  2.         /// 异步分析下载
  3.         /// </summary>
  4.         private void AsyncAnalyzeAndDownload(string url, string savePath)
  5.         {
  6.             this.uriString = url;
  7.             this.savePath = savePath;

  8.             #region 分析计时开始

  9.             count = 0;
  10.             count1 = 0;
  11.             freq = 0;
  12.             result = 0;

  13.             QueryPerformanceFrequency(ref freq);
  14.             QueryPerformanceCounter(ref count);

  15.             #endregion

  16.             using (WebClient wClient = new WebClient())
  17.             {
  18.                 AutoResetEvent waiter = new AutoResetEvent(false);
  19.                 wClient.Credentials = CredentialCache.DefaultCredentials;
  20.                 wClient.DownloadDataCompleted += new DownloadDataCompletedEventHandler(AsyncURIAnalyze);
  21.                 wClient.DownloadDataAsync(new Uri(uriString), waiter);
  22.                 //waiter.WaitOne();    //阻止当前线程,直到收到信号
  23.             }
  24.                 
  25.         }

  26.         /// <summary>
  27.         /// 异步分析
  28.         /// </summary>
  29.         protected void AsyncURIAnalyze(Object sender, DownloadDataCompletedEventArgs e)
  30.         {
  31.             AutoResetEvent waiter = (AutoResetEvent)e.UserState;
  32.             try
  33.             {
  34.                 if (!e.Cancelled && e.Error == null)
  35.                 {
  36.                     
  37.                     string dnDir = string.Empty;
  38.                     string domainName = string.Empty;
  39.                     string uri = uriString;

  40.                     //获得域名 [url]http://www.sina.com/[/url]
  41.                     Match match = Regex.Match(uri, @"((http(s)?://)?)+[\w-.]+[^/]");//, RegexOptions.IgnoreCase
  42.                     domainName = match.Value;

  43.                     //获得域名最深层目录 [url]http://www.sina.com/mail/[/url]
  44.                     if (domainName.Equals(uri))
  45.                         dnDir = domainName;
  46.                     else
  47.                         dnDir = uri.Substring(0, uri.LastIndexOf('/'));

  48.                     dnDir += '/';
  49.                     
  50.                     //获取数据
  51.                     string pageData = Encoding.UTF8.GetString(e.Result);
  52.                     List<string> urlList = new List<string>();

  53.                     //匹配全路径
  54.                     match = Regex.Match(pageData, @"((http(s)?://)?)+(((/?)+[\w-.]+(/))*)+[\w-./]+\.+(" + ImageType + ")"); //, RegexOptions.IgnoreCase
  55.                     while (match.Success)
  56.                     {
  57.                         string item = match.Value;
  58.                         //短路径处理
  59.                         if (item.IndexOf("http://") == -1 && item.IndexOf("https://") == -1)
  60.                             item = (item[0] == '/' ? domainName : dnDir) + item;

  61.                         if (!urlList.Contains(item))
  62.                         {
  63.                             urlList.Add(item);
  64.                             imgUrlList.Add(item);

  65.                             //实时显示分析结果
  66.                             AddlbShowItem(item);

  67.                             //边分析边下载
  68.                             WebRequest hwr = WebRequest.Create(item);
  69.                             hwr.BeginGetResponse(new AsyncCallback(AsyncDownLoad), hwr);
  70.                             //hwr.Timeout = "0x30D40";        //默认 0x186a0 -> 100000 0x30D40 -> 200000
  71.                             //hwr.Method = "POST";
  72.                             //hwr.C;
  73.                             //hwr.MaximumAutomaticRedirections = 3;
  74.                             //hwr.Accept ="image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*";
  75.                             //hwr.Accept = "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*";
  76.                             //IAsyncResult iar = hwr.BeginGetResponse(new AsyncCallback(AsyncDownLoad), hwr);
  77.                             //iar.AsyncWaitHandle.WaitOne();
  78.                         }
  79.                         match = match.NextMatch();
  80.                     }
  81.                 }
  82.             }
  83.             finally
  84.             {
  85.                 waiter.Set();

  86.                 #region 分析计时结束

  87.                 QueryPerformanceCounter(ref count1);
  88.                 count = count1 - count;
  89.                 result = (double)(count) / (double)freq;

  90.                 toolStripStatusLabel1.Text = "分析完毕!";
  91.                 toolStripStatusLabel2.Text = string.Format(" | 分析耗时:{0}秒", result);
  92.                 Application.DoEvents();

  93.                 #endregion

  94.                 //分析完毕
  95.                 isAnalyzeComplete = true;
  96.             }
  97.         }
复制代码
这两个方法主要是用WebClient来请求然后异步获得网址所返回的数据并对数据分析,提取图片链接,提取主要有两种方式:一种是完整路径的图片链接;一种是短路径的链接,比如/images/bg.gif,程序会自动为其加上域名部分组成完整的链接。

    2.    异步下载部分代码
  1.         /// <summary>
  2.         /// 异步接受数据
  3.         /// </summary>
  4.         /// <param name="asyncResult"></param>
  5.         public  void AsyncDownLoad(IAsyncResult asyncResult)  
  6.         {
  7.             #region 下载计时开始

  8.             if (cfreq == 0)
  9.             {
  10.                 QueryPerformanceFrequency(ref cfreq);
  11.                 QueryPerformanceCounter(ref ccount);
  12.             }

  13.             #endregion

  14.             WebRequest request = (WebRequest)asyncResult.AsyncState;
  15.             string url = request.RequestUri.ToString();
  16.             try
  17.             {
  18.                 WebResponse response = request.EndGetResponse(asyncResult);
  19.                 using (Stream stream = response.GetResponseStream())
  20.                 {
  21.                     Image img = Image.FromStream(stream);
  22.                     string[] tmpUrl = url.Split('.');
  23.                     img.Save(string.Concat(savePath, "/", DateTime.Now.ToString("yyyyMMddHHmmssfff"), ".", tmpUrl[tmpUrl.Length - 1]));
  24.                     img.Dispose();
  25.                     stream.Close();
  26.                 }
  27.                 allDone.Set();

  28.                 //从未下载的列表中删除已经下载的图片
  29.                 imgUrlList.Remove(url);

  30.                 //更新列表框
  31.                 int indexItem = this.lbShow.Items.IndexOf(url);
  32.                 if (indexItem >= 0 && indexItem <= this.lbShow.Items.Count)
  33.                     SetlbShowItem(indexItem);
  34.             }
  35.             catch (Exception)
  36.             {
  37.                 imgUrlList.Remove(url);
  38.             }
  39.         }
复制代码
这部分就是异步下载图片并保存的代码,调用部分请看AsyncURIAnalyze方法分析图片链接匹配成功后就开始进行图片下载,每下载完一张图片就更新显示在界面正下方List框内(在链接前标记√ )。  

    篇幅有限,还有一起其他重要的代码如 实时显示分析和下载结果 的代码请下载源代码查看。另外需要注意的是输入需要下载图片的网址的时候需要输入完整的链接,带http如 http://www.sina.com 。

程序和代码

执行文件和源码下载:
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值