如何怎么编写程序c#程序获取某个网页的大小

网络爬虫在信息检索与处理中有很大的作用,是收集网络信息的重要工具。
接下来就介绍一下爬虫的简单实现。
爬虫的工作流程如下
爬虫自指定的URL地址开始下载网络资源,直到该地址和所有子地址的指定资源都下载完毕为止。
下面开始逐步分析爬虫的实现。
1. 待下载集合与已下载集合
为了保存需要下载的URL,同时防止重复下载,我们需要分别用了两个集合来存放将要下载的URL和已经下载的URL。
因为在保存URL的同时需要保存与URL相关的一些其他信息,如深度,所以这里我采用了Dictionary来存放这些URL。
具体类型是Dictionary&string, int& 其中string是Url字符串,int是该Url相对于基URL的深度。
每次开始时都检查未下载的集合,如果已经为空,说明已经下载完毕;如果还有URL,那么就取出第一个URL加入到已下载的集合中,并且下载这个URL的资源。
2. HTTP请求和响应
C#已经有封装好的HTTP请求和响应的类HttpWebRequest和HttpWebResponse,所以实现起来方便不少。
为了提高下载的效率,我们可以用多个请求并发的方式同时下载多个URL的资源,一种简单的做法是采用异步请求的方法。
控制并发的数量可以用如下方法实现
1 private void DispatchWork()
if (_stop) //判断是否中止下载
for (int i = 0; i & _reqC i++)
if (!_reqsBusy[i]) //判断此编号的工作实例是否空闲
RequestResource(i); //让此工作实例请求资源
&由于没有显式开新线程,所以用一个工作实例来表示一个逻辑工作线程
1 private bool[] _reqsBusy = null; //每个元素代表一个工作实例是否正在工作
2 private int _reqCount = 4; //工作实例的数量
&每次一个工作实例完成工作,相应的_reqsBusy就设为false,并调用DispatchWork,那么DispatchWork就能给空闲的实例分配新任务了。
&接下来是发送请求
1 private void RequestResource(int index)
string url = "";
lock (_locker)
if (_urlsUnload.Count &= 0) //判断是否还有未下载的URL
_workingSignals.FinishWorking(index); //设置工作实例的状态为Finished
_reqsBusy[index] = true;
_workingSignals.StartWorking(index); //设置工作状态为Working
depth = _urlsUnload.First().V //取出第一个未下载的URL
url = _urlsUnload.First().K
_urlsLoaded.Add(url, depth); //把该URL加入到已下载里
_urlsUnload.Remove(url); //把该URL从未下载中移除
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
req.Method = _ //请求方法
req.Accept = _ //接受的内容
req.UserAgent = _userA //用户代理
RequestState rs = new RequestState(req, url, depth, index); //回调方法的参数
var result = req.BeginGetResponse(new AsyncCallback(ReceivedResource), rs); //异步请求
ThreadPool.RegisterWaitForSingleObject(result.AsyncWaitHandle, //注册超时处理方法
TimeoutCallback, rs, _maxTime, true);
catch (WebException we)
MessageBox.Show("RequestResource " + we.Message + url + we.Status);
第7行为了保证多个任务并发时的同步,加上了互斥锁。_locker是一个Object类型的成员变量。
第9行判断未下载集合是否为空,如果为空就把当前工作实例状态设为Finished;如果非空则设为Working并取出一个URL开始下载。当所有工作实例都为Finished的时候,说明下载已经完成。由于每次下载完一个URL后都调用DispatchWork,所以可能激活其他的Finished工作实例重新开始工作。
第26行的请求的额外信息在异步请求的回调方法作为参数传入,之后还会提到。
第27行开始异步请求,这里需要传入一个回调方法作为响应请求时的处理,同时传入回调方法的参数。
第28行给该异步请求注册一个超时处理方法TimeoutCallback,最大等待时间是_maxTime,且只处理一次超时,并传入请求的额外信息作为回调方法的参数。
RequestState的定义是
1 class RequestState
private const int BUFFER_SIZE = 131072; //接收数据包的空间大小
private byte[] _data = new byte[BUFFER_SIZE]; //接收数据包的buffer
private StringBuilder _sb = new StringBuilder(); //存放所有接收到的字符
public HttpWebRequest Req { get; private set; } //请求
public string Url { get; private set; } //请求的URL
public int Depth { get; private set; } //此次请求的相对深度
public int Index { get; private set; } //工作实例的编号
public Stream ResStream { get; set; } //接收数据流
public StringBuilder Html
public byte[] Data
public int BufferSize
return BUFFER_SIZE;
public RequestState(HttpWebRequest req, string url, int depth, int index)
TimeoutCallback的定义是
1 private void TimeoutCallback(object state, bool timedOut)
if (timedOut) //判断是否是超时
RequestState rs = state as RequestS
if (rs != null)
rs.Req.Abort(); //撤销请求
_reqsBusy[rs.Index] = false; //重置工作状态
DispatchWork(); //分配新任务
接下来就是要处理请求的响应了
1 private void ReceivedResource(IAsyncResult ar)
RequestState rs = (RequestState)ar.AsyncS //得到请求时传入的参数
HttpWebRequest req = rs.R
string url = rs.U
HttpWebResponse res = (HttpWebResponse)req.EndGetResponse(ar); //获取响应
if (_stop) //判断是否中止下载
res.Close();
req.Abort();
if (res != null && res.StatusCode == HttpStatusCode.OK) //判断是否成功获取响应
Stream resStream = res.GetResponseStream(); //得到资源流
rs.ResStream = resS
var result = resStream.BeginRead(rs.Data, 0, rs.BufferSize, //异步请求读取数据
new AsyncCallback(ReceivedData), rs);
else //响应失败
res.Close();
rs.Req.Abort();
_reqsBusy[rs.Index] = false; //重置工作状态
DispatchWork(); //分配新任务
catch (WebException we)
MessageBox.Show("ReceivedResource " + we.Message + url + we.Status);
第19行这里采用了异步的方法来读数据流是因为我们之前采用了异步的方式请求,不然的话不能够正常的接收数据。
该异步读取的方式是按包来读取的,所以一旦接收到一个包就会调用传入的回调方法ReceivedData,然后在该方法中处理收到的数据。
该方法同时传入了接收数据的空间rs.Data和空间的大小rs.BufferSize。
接下来是接收数据和处理
1 private void ReceivedData(IAsyncResult ar)
RequestState rs = (RequestState)ar.AsyncS //获取参数
HttpWebRequest req = rs.R
Stream resStream = rs.ResS
string url = rs.U
int depth = rs.D
string html = null;
int index = rs.I
int read = 0;
read = resStream.EndRead(ar); //获得数据读取结果
if (_stop)//判断是否中止下载
rs.ResStream.Close();
req.Abort();
if (read & 0)
MemoryStream ms = new MemoryStream(rs.Data, 0, read); //利用获得的数据创建内存流
StreamReader reader = new StreamReader(ms, _encoding);
string str = reader.ReadToEnd(); //读取所有字符
rs.Html.Append(str); // 添加到之前的末尾
var result = resStream.BeginRead(rs.Data, 0, rs.BufferSize, //再次异步请求读取数据
new AsyncCallback(ReceivedData), rs);
html = rs.Html.ToString();
SaveContents(html, url); //保存到本地
string[] links = GetLinks(html); //获取页面中的链接
AddUrls(links, depth + 1); //过滤链接并添加到未下载集合中
_reqsBusy[index] = false; //重置工作状态
DispatchWork(); //分配新任务
catch (WebException we)
MessageBox.Show("ReceivedData Web " + we.Message + url + we.Status);
第14行获得了读取的数据大小read,如果read&0说明数据可能还没有读完,所以在27行继续请求读下一个数据包;
如果read&=0说明所有数据已经接收完毕,这时rs.Html中存放了完整的HTML数据,就可以进行下一步的处理了。
第26行把这一次得到的字符串拼接在之前保存的字符串的后面,最后就能得到完整的HTML字符串。
然后说一下判断所有任务完成的处理
1 private void StartDownload()
_checkTimer = new Timer(new TimerCallback(CheckFinish), null, 0, 300);
DispatchWork();
7 private void CheckFinish(object param)
if (_workingSignals.IsFinished()) //检查是否所有工作实例都为Finished
_checkTimer.Dispose(); //停止定时器
_checkTimer = null;
if (DownloadFinish != null && _ui != null) //判断是否注册了完成事件
_ui.Dispatcher.Invoke(DownloadFinish, _index); //调用事件
第3行创建了一个定时器,每过300ms调用一次CheckFinish来判断是否完成任务。第15行提供了一个完成任务时的事件,可以给客户程序注册。_index里存放了当前下载URL的个数。
该事件的定义是
1 public delegate void DownloadFinishHandler(int count);
3 /// &summary&
4 /// 全部链接下载分析完毕后触发
5 /// &/summary&
6 public event DownloadFinishHandler DownloadFinish = null;
阅读(...) 评论()
Copyright &copy2013 Jiajun. All Rights Reserved.(window.slotbydup = window.slotbydup || []).push({
id: '1102523',
container: s,
size: '180,30',
display: 'inlay-fix'
第一个C#程序Hello World
发布日期: 13:48
来源:未知
&一、编写第一个C#程序——Hello World1. 启动Microsoft Visual Studio 2010。2. 点击“文件”菜单,选择“新建”项,在弹出的子菜单中选择“项目”命令。如下图所示:3. 弹出“新建项目”对话框。如下图所示:4. 在“最近的模板”下面点击“Visual C#”项,在中间的“模板”窗口中选择“控制台应用程序”项,在底部“名称”文本框中输入项目名称“HelloWorld”,点击“浏览”按钮,选择项目保存的位置“F:\VStudio2010\”。5. 点击“确定”按钮,弹出下面的“HelloWorld”窗口:6. 在static void Main(string[] args){下面添加如下的代码(以“//”开头的是注释):// 第一个C#程序Hello World - // Console类位于System命名空间,表示控制台应用程序的标准输入流、输出流和错误流// Console.WriteLine方法将指定的数据(后跟当前行终止符)写入标准输出流// Console.ReadLine方法使程序暂停下来,直到按下回车键才会继续运行Console.WriteLine(&Hello World!&);Console.ReadLine();7. 添加好代码的窗口如下图所示:窗口中Program.cs文件的完整代码如下:&using Susing System.Collections.Gusing System.Lusing System.Tnamespace HelloWorld{&&& class Program&&& {&&&&&&& static void Main(string[] args)&&&&&&& {&&&&&&&&&&& // 第一个C#程序Hello World -&&&&&&&&&&&& // Console类位于System命名空间内,表示控制台应用程序的标准输入流、输出流&&&&&&&&&&& // 和错误流&&&&&&&&&&& // Console.WriteLine方法将指定的数据(后跟当前行终止符)写入标准输出流&&&&&&&&&&& // Console.ReadLine方法使程序暂停下来,直到按下回车键才会继续运行&&&&&&&&&&& Console.WriteLine(&Hello World!&);&&&&&&&&&&& Console.ReadLine();&&&&&&& }&&& }}注释可以省略!8. 选择“文件”菜单,点击“全部保存”命令,或者按下Ctrl+Shift+S快捷键,保存所有文件。9. 选择“调试”菜单,点击“启动调试”命令,或者按下F5键,运行程序。10. 运行结果如下:11. 按下回车键(Enter),结束程序的运行。至此,第一个C#程序——Hello World编写成功!二、代码分析C#语言的程序结构包括程序、命名空间、类型、成员和程序集。o程序:C#程序包含一个或多个源文件。每一个C#程序由一个或多个类组成。所有的C#程序都必须封装在某个类中。o命名空间:程序中声明的类型、类型中包含的成员都能够被组织到命名空间中。o类型:类和接口是类型的例子。o成员:字段、方法、属性和事件是成员的例子。o程序集:程序集的文件扩展名一般是.exe(应用程序)或者.dll(类库)。当C#程序被编译时,它们会被打包到程序集中。1. 导入命名空间&using S&&&&&&&&&&&&&&&&&&&&& // 命名空间using System.Collections.G& // 子命名空间using System.L&&&&&&&&&&&&&&&& // 子命名空间using System.T&&&&&&&&&&&&&&&& // 子命名空间上述代码使用using指令导入命名空间,以便使用类型而不用再指定命名空间。编译器会在using指令指定的命名空间中查找没有在当前命名空间中定义,但是在代码中引用的类。就是说,类必须位于命名空间中。要么它在导入的命名空间中;要么它在当前的命名空间中定义。在Program.cs文件中使用using的原因是下面要使用一个库类System.Console。using System指令允许把这个类简写为Console。几乎所有的C#程序都使用System命名空间中的类,所以所有的代码文件都包含有using S语句。2. 声明命名空间&namespace HelloWorld{}使用namespace关键字声明了一个命名空间范围。其后花括号中的所有代码都被认为是在这个命名空间中。3. 命名空间的总结命名空间有两种,一种是系统命名空间,一种是用户自定义命名空间。一个源程序文件中可以包含多个命名空间;同一命名空间可以在多个源程序文件中定义。命名空间可以嵌套。同一命名空间中不允许定义重名的类型(类或者方法等)。同名的两个类如果在不同的命名空间中,相互之间是不会混淆的。1)命名空间的引用:using 命名空间名称;一般写在源文件的最前面。2)命名空间的声明:&namespace 命名空间名称{}3)在程序中访问其它命名空间中的方法:&Namespace&[.&Subnamespace&].类型例如:System.Console.WriteLine(&zz.cn&);在这里,C#用点“.”操作符表示了语句的从属关系。oSystem:命名空间oConsole:类oWriteLine:方法4. 声明类class Program{}使用class关键字声明一个类,类的名称为Program。因为该类位于HelloWorld命名空间中,所以该类的完整名称应该是HelloWorld.Program。类的声明包括class关键字,后面是类名和一对花括号。与类相关的所有代码都应放在这对花括号中。5. 声明Main方法&static void Main(string[] args){&&& // 应用程序功能代码实现位置}声明类的Main方法:ostatic:返回值的类型。ovoid:返回值。oMain:方法名称。ostring[] args:“Main”方法的参数。这是一个字符串数组。“Main”方法是每一个C#应用程序的入口,C#要求每个程序必须且只能有一个“Main”方法,“Main”方法必须放在任意一个类中。对于被调用的“Main”方法来说,它所在的类不需要被实例化。如果有多个“Main”方法,编译器就会返回一个错误!“Main”方法的声明与结构如下:方法一:不带参数,返回void&static void Main(){&&& // ...}方法二:不带参数,返回int&static int Main(){&&& // ...&&& return 0;}方法三:带参数,返回void&static void Main(string[] args){&&& // ...}方法四:带参数,返回int&static int Main(string[] args){&&& // ...&&& return 0;}6. 语句&Console.WriteLine(&Hello World!&);Console.ReadLine();上面的代码调用了System.Console类的WriteLine()方法和ReadLine()方法。语句就是C#应用程序中执行操作的指令。C#中的语句必须用分号“;”结束。可以在一行中书写多条语句,也可以将一条语句书写在多行上。7. 花括号语法在C#中,花括号“{”和“}”是一种范围标志,是组织代码的一种方式,用于标识应用程序中逻辑上有紧密联系的一段代码的开始与结束。花括号可以嵌套,以表示应用程序中的不同层次。8. C#注释C#注释分为两种:单行注释和多行注释。1)单行注释用两个正斜线来表示“//”:// 右边的文字都是注释,直到一行结束。在“//”的后面不能使用反斜杠“\”。2)多行注释以“/*”开始,以“*/”结束:/* 这是多行注释......*/多行注释不能嵌套,即在分割符“/*”和“*/”之间不能再有分割符。3)文档注释在Visual Studio的开发工具中,目前只有C#编译器能够将注释转换成XML文件。方法是使用“///”符号。只要加上这个注释符号和代表XML元素的标记,就可以将注释转换成XML文件。所以文档注释又可以称为XML注释。比如:using Susing System.Collections.Gusing System.Lusing System.Tnamespace HelloWorld{&&& /// &summary&&&& /// 生成XML注释文件范例&&& /// &/summary&&&& class Program&&& {&&&&&&& /// &summary&&&&&&&& /// Program类,打印Hello World!&&&&&&& /// &/summary&&&&&&&& /// &param name=&args&&命令行参数&/param&&&&&&&& static void Main(string[] args)&&&&&&& {&&&&&&&&&&& // Console类位于System命名空间内,表示控制台应用程序的标准输入流、输出流&&&&&&&&&&& // 和错误流&&&&&&&&&&& // Console.WriteLine方法将指定的数据(后跟当前行终止符)写入标准输出流&&&&&&&&&&& // Console.ReadLine方法使程序暂停下来,直到按下回车键才会继续运行&&&&&&&&&&& Console.WriteLine(&Hello World!&);&&&&&&&&&&& Console.ReadLine();&&&&&&& }&&& }}注意:定义的XML元素一定要遵守XML的格式。如果编译成功,我们就可以找到HelloWorld.XML文件。附:在Visual Studio 2010中设置生成XML注释文件的步骤:以项目HelloWorld为例,点击“项目”菜单,选择“HelloWorld 属性”命令。如下图所示:选择“HelloWorld 属性”命令打开“HelloWorld”窗口。如下图所示:“HelloWorld”窗口在左边点击“生成”项,在右边选择“XML文档文件”项即可。XML文件名会自动填写,当然也可以自行修改。&
(window.slotbydup = window.slotbydup || []).push({
id: '1063561',
container: s,
size: '230,230',
display: 'inlay-fix'
C#语言是一门简单,现代,优雅,面向对象,类型安全,平台独立的一门新型组件编程语言。其语法风格源自C/C++家族,融合了Visual Basic的高效和C/C++强大。其优雅的语法风格,创新的语言特性,因而深受世界各地程序员的好评和喜爱。本期专题从C#的基础语法、类、面向对像、数组、设计模式、开发技巧等知识讲解C#,力求对C#做一个简单明了的说明。目的是向读者提供对语言的入门介绍,以便于读者能够快速上手编写程序。
免责声明:以上教程信息由会员自行搜集、整理、发布,内容的真实性、准确性和合法性由发布会员负责。站长学院对此不承担任何责任。

我要回帖

更多关于 程序编写 的文章

 

随机推荐