网络爬虫一
作者:Aliot
发布时间:2017-07-10
评论:0
阅读:1
网络爬虫在信息检索与处理中有很大的作用,是收集网络信息的重要工具。
接下来就介绍一下爬虫的简单实现。
爬虫的工作流程如下
爬虫自指定的URL地址开始下载网络资源,直到该地址和所有子地址的指定资源都下载完毕为止。http://mmm.qqq23.com
下面开始逐步分析爬虫的实现。
1. 待下载集合与已下载集合
为了保存需要下载的URL,同时防止重复下载,我们需要分别用了两个集合来存放将要下载的URL和已经下载的URL。
因为在保存URL的同时需要保存与URL相关的一些其他信息,如深度,所以这里我采用了Dictionary来存放这些URL。
具体类型是Dictionary 其中string是Url字符串,int是该Url相对于基URL的深度。
每次开始时都检查未下载的集合,如果已经为空,说明已经下载完毕;如果还有URL,那么就取出第一个URL加入到已下载的集合中,并且下载这个URL的资源。
2. HTTP请求和响应
C#已经有封装好的HTTP请求和响应的类HttpWebRequest和HttpWebResponse,所以实现起来方便不少。
为了提高下载的效率,http://www.qqq100.com 我们可以用多个请求并发的方式同时下载多个URL的资源,一种简单的做法是采用异步请求的方法。
控制并发的数量可以用如下方法实现
1 private void DispatchWork()
2 {
3 if (_stop) //判断是否中止下载
4 {
5 return;
6 }
7 for (int i = 0; i < _reqCount; i++)
8 {
9 if (!_reqsBusy[i]) //判断此编号的工作实例是否空闲
10 {
11 RequestResource(i); //让此工作实例请求资源
12 }
13 }
14 }
由于没有显式开新线程,所以用一个工作实例来表示一个逻辑工作线程
1 private bool[] _reqsBusy = null; //每个元素代表一个工作实例是否正在工作
2 private int _reqCount = 4; //工作实例的数量
每次一个工作实例完成工作,相应的_reqsBusy就设为false,并调用DispatchWork,那么DispatchWork就能给空闲的实例分配新任务了。
接下来是发送请求
1 private void RequestResource(int index)
2 {
3 int depth;
4 string url = "";
5 try
6 {
7 lock (_locker)
8 {
9 if (_urlsUnload.Count <= 0)
10 {
11 _workingSignals.FinishWorking(index);
12 return;
13 }
14 _reqsBusy[index] = true;
15 _workingSignals.StartWorking(index);
16 depth = _urlsUnload.First().Value;
17 url = _urlsUnload.First().Key;
18 _urlsLoaded.Add(url, depth);
19 _urlsUnload.Remove(url);
20 }
21
22 HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
23 req.Method = _method; //请求方法
24 req.Accept = _accept; //接受的内容
25 req.UserAgent = _userAgent; //用户代理
26 RequestState rs = new RequestState(req, url, depth, index); //回调方法的参数
27 var result =
req.BeginGetResponse(new AsyncCallback(ReceivedResource), rs); //异步请求
28 ThreadPool.RegisterWaitForSingleObject(result.AsyncWaitHandle, //注册超时处理方法
29 TimeoutCallback, rs, _maxTime, true);
30 }
31 catch (WebException we)
32 {
33 MessageBox.Show("RequestResource
" + we.Message + url + we.Status);
34 }
35 }
第26行的请求的额外信息在异步请求的回调方法作为参数传入,之后还会提到。
第27行开始异步请求,这里需要传入一个回调方法作为响应请求时的处理,同时传入回调方法的参数。
第28行给该异步请求注册一个超时处理方法TimeoutCallback,最大等待时间是_maxTime,且只处理一次超时,并传入请求的额外信息作为回调方法的参数。
未完待续.......