C#爬虫

前言

最近两周在学习爬虫相关的知识,看过爬虫原理之后,就想自己也写一个简单的爬虫工具,实现功能,就是文本框中输入要爬取的基地址,然后点击开始爬取按钮,把爬取的内容保存到本地。虽然Python更是适合写爬虫,但是谁让我是搞C#的呢,只能用C#写了。

知识准备

写代码之前,需要了解基本的爬虫原理和步骤才能在写代码的时候,做到心中有数。调试的时候,才会知根知底。百度了两篇关于爬虫原理和代码的博客,写的非常好,通俗易懂。
参考一
参考二
知道原理之后,就可以动手写代码了。写的代码也不是完全自己写,而是从CodePlex上面发现的一个开源的C#爬虫程序,源代码
代码下载下来,可以自己研究我就不多说了。

问题

写代码的时候,遇到了几个自己不熟悉的知识点,在这里记录下来帮助自己以后随时查看

  1. 委托
    其实在写代码的时候,委托主要用在事件处理方法中,这里主要说说这方面的知识吧,以后遇到其他的再写。
    使用C#编程,无论是WinForm,WebForm 给人很难忘得就是它的控件,而他们的控件库使用方式都是使用使用事件驱动模式,而事件驱动模式却少不了委托。话不多说,看代码能够更清好的理解事件和委托之间的联系.
 public delegate void MyDelegate(string name);
    public class EventSource
    {
        public event MyDelegate Event_Delegate;

        public void SetCustomer(string name)
        {
            Console.WriteLine("事件发生.....\n");
            Console.WriteLine("hi! "+name);
        }

        public void TestEvent()
        {
            EventSource source = new EventSource();
            Console.WriteLine("订阅事件.....\n");
            source.Event_Delegate += new MyDelegate(source.SetCustomer);
            Console.WriteLine("触发事件.....\n");
            source.Event_Delegate("hechen");
            Console.WriteLine("..................");
        }
    }

上面的代码中我们定义了一个委托,然后定义了一个类EventSource,这个类中声明了一个事件。定义一个事件使用event 关键字,定义一个event必须指定这个event传递消息的委托,在触发事件之前必需订阅事件,我们使用+= new 语法来订阅一个事件,也就相当于实例化一个事件。当我们触发事件的时候,就会调用相应的方法去处理。关于委托的知识绝对不是几句话能讲清楚的,下面的事件也是一样,只能在以后的使用中逐渐体会个中深意。博客园上面有很多关于委托和事件的文章,其中写的非常好,我在这里就不班门弄斧。
2. 事件
事件类似于异常,因为他们都有对象引发,并且可以通过我们提供的代码来处理。事件必须订阅,订阅一个事件的含义是提供代码,在事件发生时执行这些代码,他们称为事件处理程序。单个事件可供多个处理程序订阅,在该事件发生时这些处理程序都会被调用,调用顺序就是订阅事件的顺序。要处理事件,必须提供一个事件处理函数,该函数必须匹配的返回类型和和参数赢该匹配事件指定的委托的返回类型和参数。
3. lambda表达式,匿名方法
个人觉得这个lambda表达式更加难以理解,lambda表达式是简化匿名方法的语法的一种方式,
看下面的一段代码

Timer myTimer = new Timer(100);
myTimer.Elapsed += new ElapsedEventHandler(WriteChar)

上面的代码订阅了Timer对象的Elapsed事件。使用匿名方法时,该过程会减少为一步:

myTimer.Elapsed += delegate(object sender, ElapsedEventArgs e)
{
    //事件处理方法WriteChar的代码
}

上面一段代码使用内联的匿名方法,该匿名方法的返回类型和参数匹配所订阅的事件需要的委托的返回类型和参数
上面两端代码主要区别是这里的匿名方法对于其余代码而言世家航是隐藏的,例如不能再程序的其他地方重应用这个事件处理程序,而且语法有点沉闷,delegate关键字还会带来混乱,因为匿名方法和委托都是用delegate来修饰。为了解决这个问题,lambda表达式是一个比较好的选择。
lambda表达式是简化匿名方法的语法的一种方式,实际上lambda表达式还有其他用处,这里暂且不说。使用lambda表达式重写上面的代码:

myTimer.Elapsed += (source , e) =>()  //()内是WriteChar事件处理函数代码

lambda表达式由三个部分组成:
1.放在括号中的参数列表
2.=>运算符
3.C#语句
可以从上下文中推断出参数类型,=>运算符只是把参数类别和C#语句分开,在调用labmda表达式时,执行表达式体,编译器会提取这个lambdaZ表达式,创建一个匿名方法,其工作方式与上述代码一致。
4. ref out关键字修饰的参数的含义
当我们在给函数传递参数的时候,有时候我们希望在函数内部修改的变量的值,在函数外部扔
对于这两个关键字修饰的参数,我的理解就是为了防止变量在超出作用域之后被打回原形所用的。这样就可以做到在函数内部对变量做出的修改在函数外部仍然能用了,它们两个区别是ref修饰的参数在传递之前必须初始化,out在传递之前不能初始化,即使初始化了,在传递到函数内部的时候初始化的值仍然要被丢掉。重新赋值。
5. C# 链表的知识

  1. URL和URI的区别
    可参考
C#中编写网络爬虫并保持cookies长久有效,通常涉及使用HttpClient或者WebRequest/WebResponse等类,以及设置CookieContainer来保存和管理cookies。以下是基本步骤: 1. **创建CookieContainer**:首先,你需要创建一个`CookieContainer`实例,这是用于存储cookie的地方。 ```csharp using System.Net; CookieContainer container = new CookieContainer(); ``` 2. **发送请求并获取cookies**:每次向服务器发起HTTP请求时,记得添加这个容器到HttpClient或WebRequest的Cookies属性中。 ```csharp HttpClient client = new HttpClient(); client.DefaultRequestHeaders.Accept.Clear(); // 如果有需要,清空默认头信息 client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); // 设置接受类型 // 使用CookieContainer发送GET请求 HttpResponseMessage response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead); if (response.IsSuccessStatusCode) { using (HttpContent content = response.Content) { var cookies = response.Cookies; // 获取响应中的cookies foreach (Cookie cookie in cookies) { container.Add(cookie); // 将cookies添加到container } } } ``` 3. **使用container发送带cookie的请求**:当你需要再次发送请求时,设置HttpClient的CookieContainer属性,它会在请求头自动带上这些cookies。 ```csharp HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, url); request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", "your_token"); // 可能需要的授权信息 client.DefaultRequestHeaders.Cookie = container.GetCookies(request.RequestUri).Cast<Cookie>().Select(c => c.ToString()).ToList(); HttpResponseMessage response = await client.SendAsync(request); ``` 4. **持久化cookies**:如果你希望cookies在程序退出后也能保持,可以考虑将CookieContainer序列化到文件或者数据库中,下次启动时再读取恢复。 5. **注意cookies的有效期**:有些cookies可能是临时的,如果它们有固定的过期时间,你需要在处理cookies时考虑这一点,避免过期。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值