.NET实现网络爬虫

转载 2018年02月09日 21:51:07

爬虫的特征和运行方式

User-Agent:主要用来将我们的爬虫伪装成浏览器。

Cookie:主要用来保存爬虫的登录状态。

连接数:主要用来限制单台机器与服务端的连接数量。

代理IP:主要用来伪装请求地址,提高单机并发数量。

爬虫工作的方式可以归纳为两种:深度优先、广度优先。

深度优先就是一个连接一个连接的向内爬,处理完成后再换一下一个连接,这种方式对于我们来说缺点很明显。
广度优先就是一层一层的处理,非常适合利用多线程并发技术来高效处理,因此我们也用广度优先的抓取方式。

首先我们用Visual Studio 2015创建一个控制台程序,定义一个简单的SimpleCrawler类,里面只包含几个简单的事件:

 public class SimpleCrawler
    {
        public SimpleCrawler() { }
        /// <summary>
        /// 爬虫启动事件
        /// </summary>
        public event EventHandler<OnStartEventArgs> OnStart;
        /// <summary>
        /// 爬虫完成事件
        /// </summary>
        public event EventHandler<OnCompletedEventArgs> OnCompleted;

        /// <summary>
        /// 爬虫出错事件
        /// </summary>
        public event EventHandler<Exception> OnError;
        /// <summary>
        /// 定义cookie容器
        /// </summary>
        public CookieContainer CookieContainer { get; set; }

    }

接着我们创建一个OnStart的事件对象:

这里写图片描述

然后我们创建一个OnCompleted事件对象:

这里写图片描述

最后我们再给它增加一个异步方法,通过User-Agent将爬虫伪装成了Chrome浏览器

 /// <summary>
        /// 异步创建爬虫
        /// </summary>
        /// <param name="uri"></param>
        /// <param name="proxy"></param>
        /// <returns></returns>
        public async Task<string> Start(Uri uri, WebProxy proxy = null)
        {
            return await Task.Run(() =>
            {
                var pageSource = string.Empty;
                try
                {
                    if (this.OnStart != null)
                        this.OnStart(this, new OnStartEventArgs(uri));
                    Stopwatch watch = new Stopwatch();
                    watch.Start();
                    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
                    request.Accept = "*/*";
                    //定义文档类型及编码
                    request.ContentType = "application/x-www-form-urlencoded";
                    request.AllowAutoRedirect = false;//禁止自动跳转
                    request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36";
                    //定义请求超时事件为5s
                    request.Timeout = 5000;
                    //长连接
                    request.KeepAlive = true;
                    request.Method = "GET";
                    //设置代理服务器IP,伪装请求地址
                    if (proxy != null)
                        request.Proxy = proxy;
                    //附加Cookie容器
                    request.CookieContainer = this.CookieContainer;
                    //定义最大链接数
                    request.ServicePoint.ConnectionLimit = int.MaxValue;
                    //获取请求响应
                    HttpWebResponse response = (HttpWebResponse)request.GetResponse();
                    //将Cookie加入容器,保持登录状态
                    foreach (Cookie cookie in response.Cookies)
                        this.CookieContainer.Add(cookie);
                    //获取响应流
                    Stream stream = response.GetResponseStream();
                    //以UTF8的方式读取流
                    StreamReader reader = new StreamReader(stream,Encoding.UTF8);
                    //获取网站资源
                    pageSource = reader.ReadToEnd();
                    watch.Stop();
                    //获取当前任务线程ID
                    var threadID = Thread.CurrentThread.ManagedThreadId;
                    //获取请求执行时间
                    var milliseconds = watch.ElapsedMilliseconds;
                    reader.Close();
                    stream.Close();
                    request.Abort();
                    response.Close();
                    if (this.OnCompleted != null)
                        this.OnCompleted(this, new OnCompletedEventArgs(uri, threadID, milliseconds, pageSource));
                }
                catch (Exception ex)
                {
                    if (this.OnError != null)
                        this.OnError(this, ex);

                }
                return pageSource;
            });
        }

在控制台里写下爬虫的抓取代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace TestPa
{
    class Program
    {
        static void Main(string[] args)
        {
            //定义入口URl
            var cityUrl = "http://hotels.ctrip.com/citylist";
            //定义泛型列表存放城市名称及对应的酒店
            var cityList = new List<City>();
            //调用自己写的爬虫程序
            var cityCrawler = new SimpleCrawler();
            cityCrawler.OnStart += (s, e) =>
              {
                  Console.WriteLine("爬虫开始抓取的地址:" + e.Uri.ToString());
              };
            cityCrawler.OnError += (s, e) =>
            {
                Console.WriteLine("爬虫抓取出现错误:" + e.Message);
            };
            cityCrawler.OnCompleted += (s, e) =>
              {
                  var links = Regex.Matches(e.PageSource, @"<a[^>]+href=""*(?<href>/hotel/[^>\s]+)""\s*[^>]*>(?<text>(?!.*img).*?)</a>", RegexOptions.IgnoreCase);
                  foreach(Match match in links)
                  {
                      var city = new City
                      {
                          CityName = match.Groups["text"].Value,
                          Uri = new Uri("http://hotels.ctrip.com" + match.Groups["href"].Value)
                      };
                      if (!cityList.Contains(city))
                          cityList.Add(city);
                      Console.WriteLine(city.CityName + "||" + city.Uri);
                  }

                  Console.WriteLine(e.PageSource);
                  Console.WriteLine("**********************************");
                  Console.WriteLine("爬虫抓取完成");
                  Console.WriteLine("耗时:" + e.Milliseconds + " 毫秒");
                  Console.WriteLine("线程:" + e.ThreadID);
                  Console.WriteLine("地址:" + e.Uri.ToString());
              };
            cityCrawler.Start(new Uri(cityUrl)).Wait();
            Console.ReadKey();
        }
    }

    public class City
    {
        public string CityName { get; set; }
        public Uri Uri { get; set; }
    }
}

运行结果:
这里写图片描述

请看大神原文地址
基于.NET更高端智能化的网络爬虫

用C#实现网络爬虫(一)

转自:http://www.cnblogs.com/Jiajun/archive/2012/06/16/2552103.html 网络爬虫在信息检索与处理中有很大的作用,是收集网络信息的重要...
  • gf771115
  • gf771115
  • 2015年04月28日 13:59
  • 3174

Java之——简单的网络爬虫实现

最近在学习搜索方面的东西,需要了解网络爬虫方面的知识,虽然有很多开源的强大的爬虫,但本着学习的态度,自己写了一个简单的网络爬虫,以便了解其中原理。 首先介绍每个类的功能: DownloadPage...
  • l1028386804
  • l1028386804
  • 2015年10月08日 23:46
  • 17995

推荐13个.Net开源的网络爬虫

.net开源爬虫比起其他语言开源爬虫少很多,而且开源质量也相对没那么好,为了让大家了解.net开源爬虫,笔者为大家收集了13款开源爬虫,希望可以帮助大家学习.net爬虫技术...
  • hguchen
  • hguchen
  • 2017年06月15日 23:17
  • 3478

网络爬虫的实现思路

网络爬虫一般我们在网络上抓取数据时,都会想到要使用网络爬虫,那我们就来看看一般网络爬虫的实现思路。设计模式爬虫的中心思想就是以最初一个Url为注入点,从这个Url抓取更多Url,并从这些网页中获取自己...
  • zhangakui002
  • zhangakui002
  • 2016年03月02日 17:09
  • 2195

网络爬虫框架设计与实现

引题 最近在看go语言的编程实现,里面有这个项目,感觉不错,在这里简 要总结和学习心得,给大家一个引路,如果想要具体了解可以看《GO 语言并发实践》 项目介绍 网络爬虫就是模拟客...
  • YID_152
  • YID_152
  • 2017年07月31日 21:11
  • 289

用URLConnection来实现简单的java网络爬虫

对于我的理解就是从别人的网站爬取数据或内容的一种工具! 好了现在我们一起用URLConnection 来爬取中国知网首页的一些数据吧! 首先定义一个工具类,来保存要爬取网页的源代码,就是爬取下面这...
  • bing2050
  • bing2050
  • 2016年05月02日 16:01
  • 2786

自己动手做网络爬虫系列——1

网络爬虫(又被称为网页蜘蛛,网络机器人),是一种按照一定的规则,自动的抓取万维网信息的程序或者脚本。另外一些不常使用的名字还有蚂蚁,自动索引,模拟程序或者蠕虫。         相信很多人都用JAVA...
  • AJAXHu
  • AJAXHu
  • 2014年01月15日 14:58
  • 3550

使用java实现网络爬虫

之前学习j2ee的搭建,基本完成了。 接下来想学习下爬虫技术。要研究一项技术,首先得知道它的原理。 那么网络爬虫的原理是什么呢? 网络爬虫是一个自动提取网页的程序,它为搜索引擎从万维网上下载网页...
  • qq_34309305
  • qq_34309305
  • 2017年03月31日 10:10
  • 896

用C#实现网络爬虫(二)

转自:http://www.cnblogs.com/Jiajun/archive/2012/06/17/2552458.html 3. 保存页面文件 这一部分可简单可复杂,如果...
  • gf771115
  • gf771115
  • 2015年04月28日 14:00
  • 1981

聚焦网络爬虫

前言:前段时间一直在忙着准备人工智能的项目答辩,其实就是编了一个很简单的网络程式——网络爬虫,然后模拟毕业论文的形式,准备开题报告,论文答辩(PPT),和论文设计(word)。刚开始很不愿意做,但是整...
  • small_baby01
  • small_baby01
  • 2013年06月30日 11:36
  • 3474
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:.NET实现网络爬虫
举报原因:
原因补充:

(最多只允许输入30个字)