用C#实现网络爬虫(二)
上一篇《用C#实现网络爬虫(一)》我们实现了网络通信的部分,接下来继续讨论爬虫的实现
3. 保存页面文件
这一部分可简单可复杂,如果只要简单地把HTML代码全部保存下来的话,直接存文件就行了。
1 private void SaveContents(string html, string url) 2 { 3 if (string.IsNullOrEmpty(html)) //判断html字符串是否有效 4 { 5 return; 6 } 7 string path = string.Format("{0}\\{1}.txt", _path, _index++); //生成文件名 8 9 try 10 { 11 using (StreamWriter fs = new StreamWriter(path)) 12 { 13 fs.Write(html); //写文件 14 } 15 } 16 catch (IOException ioe) 17 { 18 MessageBox.Show("SaveContents IO" + ioe.Message + " path=" + path); 19 } 20 21 if (ContentsSaved != null) 22 { 23 _ui.Dispatcher.Invoke(ContentsSaved, path, url); //调用保存文件事件 24 } 25 }
第23行这里又出现了一个事件,是保存文件之后触发的,客户程序可以之前进行注册。
1 public delegate void ContentsSavedHandler(string path, string url); 2 3 /// <summary> 4 /// 文件被保存到本地后触发 5 /// </summary> 6 public event ContentsSavedHandler ContentsSaved = null;
4. 提取页面链接
提取链接用正则表达式就能搞定了,不懂的可以上网搜。
下面的字符串就能匹配到页面中的链接
http://([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)?
详细见代码
1 private string[] GetLinks(string html) 2 { 3 const string pattern = @"http://([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)?"; 4 Regex r = new Regex(pattern, RegexOptions.IgnoreCase); //新建正则模式 5 MatchCollection m = r.Matches(html); //获得匹配结果 6 string[] links = new string[m.Count]; 7 8 for (int i = 0; i < m.Count; i++) 9 { 10 links[i] = m[i].ToString(); //提取出结果 11 } 12 return links; 13 }
5. 链接的过滤
不是所有的链接我们都需要下载,所以通过过滤,去掉我们不需要的链接
这些链接一般有:
- 已经下载的链接
- 深度过大的链接
- 其他的不需要的资源,如图片、CSS等
1 //判断链接是否已经下载或者已经处于未下载集合中 2 private bool UrlExists(string url) 3 { 4 bool result = _urlsUnload.ContainsKey(url); 5 result |= _urlsLoaded.ContainsKey(url); 6 return result; 7 } 8 9 private bool UrlAvailable(string url) 10 { 11 if (UrlExists(url)) 12 { 13 return false; //已经存在 14 } 15 if (url.Contains(".jpg") || url.Contains(".gif") 16 || url.Contains(".png") || url.Contains(".css") 17 || url.Contains(".js")) 18 { 19 return false; //去掉一些图片之类的资源 20 } 21 return true; 22 } 23 24 private void AddUrls(string[] urls, int depth) 25 { 26 if (depth >= _maxDepth) 27 { 28 return; //深度过大 29 } 30 foreach (string url in urls) 31 { 32 string cleanUrl = url.Trim(); //去掉前后空格 33 cleanUrl = cleanUrl.TrimEnd('/'); //统一去掉最后面的'/' 34 if (UrlAvailable(cleanUrl)) 35 { 36 if (cleanUrl.Contains(_baseUrl)) 37 { 38 _urlsUnload.Add(cleanUrl, depth); //是内链,直接加入未下载集合 39 } 40 else 41 { 42 // 外链处理 43 } 44 } 45 } 46 }
第34行的_baseUrl是爬取的基地址,如http://news.sina.com.cn/,将会保存为news.sina.com.cn,当一个URL包含此字符串时,说明是该基地址下的链接;否则为外链。
_baseUrl的处理如下,_rootUrl是第一个要下载的URL
1 /// <summary> 2 /// 下载根Url 3 /// </summary> 4 public string RootUrl 5 { 6 get 7 { 8 return _rootUrl; 9 } 10 set 11 { 12 if (!value.Contains("http://")) 13 { 14 _rootUrl = "http://" + value; 15 } 16 else 17 { 18 _rootUrl = value; 19 } 20 _baseUrl = _rootUrl.Replace("www.", ""); //全站的话去掉www 21 _baseUrl = _baseUrl.Replace("http://", ""); //去掉协议名 22 _baseUrl = _baseUrl.TrimEnd('/'); //去掉末尾的'/' 23 } 24 }
至此,基本的爬虫功能实现就介绍完了。
最后附上源代码和DEMO程序,爬虫的源代码在Spider.cs中,DEMO是一个WPF的程序,Test里是一个控制台的单线程版版本。
在下一期中,我们将介绍一些提取出网页中有效信息的方法,敬请期待。。。
用C#实现网络爬虫(二)的更多相关文章
- Python初学者之网络爬虫(二)
声明:本文内容和涉及到的代码仅限于个人学习,任何人不得作为商业用途.转载请附上此文章地址 本篇文章Python初学者之网络爬虫的继续,最新代码已提交到https://github.com/octans ...
- NodeJs 入门到放弃 — 常用模块及网络爬虫(二)
码文不易啊,转载请带上本文链接呀,感谢感谢 https://www.cnblogs.com/echoyya/p/14473101.html 目录 码文不易啊,转载请带上本文链接呀,感谢感谢 https ...
- Python网络爬虫(二)
Urllib库之解析链接 Urllib库里有一个parse这个模块,定义了处理URL的标准接口,实现 URL 各部分的抽取,合并以及链接转换.它支持如下协议的 URL 处理:file.ftp.goph ...
- 【Python网络爬虫二】使用urllib2抓去网页内容
在Python中通过导入urllib2组件,来完成网页的抓取工作.在python3.x中被改为urllib.request. 爬取具体的过程类似于使用程序模拟IE浏览器的功能,把URL作为HTTP请求 ...
- Python网络爬虫与如何爬取段子的项目实例
一.网络爬虫 Python爬虫开发工程师,从网站某一个页面(通常是首页)开始,读取网页的内容,找到在网页中的其它链接地址,然后通过这些链接地址寻找下一个网页,这样一直循环下去,直到把这个网站所有的网页 ...
- Golang 网络爬虫框架gocolly/colly 二 jQuery selector
Golang 网络爬虫框架gocolly/colly 二 jQuery selector colly框架依赖goquery库,goquery将jQuery的语法和特性引入到了go语言中.如果要灵活自如 ...
- C语言Linix服务器网络爬虫项目(二)项目设计和通过一个http请求抓取网页的简单实现
我们通过上一篇了解了爬虫具体要实现的工作之后,我们分析得出的网络爬虫的基本工作流程如下: 1.首先选取一部分精心挑选的种子URL: 2.将这些URL放入待抓取URL队列: 3.从待抓取URL队列中取出 ...
- Python3爬虫(二)网络爬虫的尺寸与约束
Infi-chu: http://www.cnblogs.com/Infi-chu/ 一.网络爬虫的尺寸: 1.小规模,数据量小,爬取速度不敏感,Requests库,爬取网页 2.中规模,数据规模较大 ...
- 【网络爬虫】【java】微博爬虫(二):如何抓取HTML页面及HttpClient使用
一.写在前面 上篇文章以网易微博爬虫为例,给出了一个很简单的微博爬虫的爬取过程,大概说明了网络爬虫其实也就这么回事,或许初次看到这个例子觉得有些复杂,不过没有关系,上篇文章给的例子只是让大家对爬虫过程 ...
- python网络爬虫之自动化测试工具selenium[二]
目录 前言 一.获取今日头条的评论信息(request请求获取json) 1.分析数据 2.获取数据 二.获取今日头条的评论信息(selenium请求获取) 1.分析数据 2.获取数据 房源案例(仅供 ...
随机推荐
- ALS数学点滴
其中,$n_{u_i}$表示用户$i$评分的电影数目,$n_{m_j}$表示对电影$j$评分的用户数目.设$I_i$表示用户$i$所评分的电影集合,则$n_{u_i}$是$I_i$的基数,同样的,$I ...
- const常量折叠
首先来看一个例子: int main(int argc, char* argv[]) { ; int *j = (int *) &i; *j=; cout<<&i<& ...
- Linux入门之——安装虚拟机软件
/** ****************************************************************************** * @author 暴走的小 ...
- Upgrade to Python 2.7.9 on CentOS5.5
1. Install python2.7 #cd /tmp #wget https://www.python.org/ftp/python/2.7.9/Python-2.7.9.tgz --no-ch ...
- JAVA 读取pdf文件
第一个路口action /* * wuhan syspro author zhangrui 2010/08/23 */ package jp.co.syspro.poo.action; import ...
- java 项目request.getParameter("")接收不到值
如果发现这个方法 以前能接收到参数,现在不能接收到参数的情况下 很有问题出来tocat 或许jak 的问题上, 换个低版本可能就好了
- IE8 placeholder兼容+Password兼容
对于placeholder兼容问题 IE系列的大部分不兼容 使用JQ插件解决这个问题,确实用法很简单 jS下载地址http://www.ijquery.cn/js/jquery.placeholder ...
- C#中的线程二(BeginInvoke和Invoke)
近日,被Control的Invoke和BeginInvoke搞的头大,就查了些相关的资料,整理如下.感谢这篇文章对我的理解Invoke和BeginInvoke的真正含义 . (一)Control的In ...
- C#word(2007)操作类--新建文档、添加页眉页脚、设置格式、添加文本和超链接、添加图片、表格处理、文档格式转化
转:http://www.cnblogs.com/lantionzy/archive/2009/10/23/1588511.html 1.新建Word文档 #region 新建Word文档/// &l ...
- 安卓开发入门之activity
安卓开发主要用到的是java语言,对于一个activity,自己写的程序可以继承至Activity,该Activity先会运行一个叫 onCreat()的类,可以在其中申明一些初始化的函数等,这个函数 ...