C#特别适合于构造蜘蛛程序,这是因为它已经内置了HTTP访问和多线程的能力,而这两种能力对于蜘蛛程序来说都是非常关键的。下面是构造一个蜘蛛程序要解决的关键问题:
(1)HTML分析:需要某种HTML解析器来分析蜘蛛程序遇到的每一个页面。
(2)页面处理:需要处理每一个下载得到的页面。下载得到的内容可能要保存到磁盘或者进一步分析处理。
(3)多线程:只有拥有多线程能力,蜘蛛程序才能真正做到高效。
(4)确定何时完成:不要小看这个问题,确定任务是否已经完成并不简单,尤其是在多线程环境下。
一、HTML解析
本文提供的HTML解析器由ParseHTML类实现,使用非常方便:首先创建该类的一个实例,然后将它的Source属性设置为要解析的HTML文档:
ParseHTML parse = new ParseHTML();
parse.Source = "Hello World
";
接下来就可以利用循环来检查HTML文档包含的所有文本和标记。通常,检查过程可以从一个测试Eof方法的while循环开始:
while(!parse.Eof())
{
char ch = parse.Parse();
if(ch==0)
{
HTMLTag tag = parse.GetTag();
}
Attribute href = tag["HREF"];
string link = href.Value;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(m_uri);
response = request.GetResponse();
stream = response.GetResponseStream();
if( !response.ContentType.ToLower().StartsWith("text/") )
{
SaveBinaryFile(response);
return null;
}
string buffer = "",line;
reader = new StreamReader(stream);
while( (line = reader.ReadLine())!=null )
{
buffer+=line+"\r\n";
}
SaveTextFile(buffer);
首先准备一个缓冲区临时地保存二进制文件的内容。 byte []buffer = new byte[1024];
接下来要确定文件保存到本地的路径和名称。如果要把一个myhost.com网站的内容下载到本地的c:\test文件夹,二进制文件的网上路径和名称是http://dotnet.chinaitlab.com/UploadFiles_6597/200901/20090104103231478.gif?http://www.xvna.com,则本地路径和名称应当是c:\test\images\logo.gif?http://www.xvna.com。与此同时,我们还要确保c:\test目录下已经创建了images子目录。这部分任务由convertFilename方法完成。
string filename = convertFilename( response.ResponseUri );
Stream outStream = File.Create( filename );
Stream inStream = response.GetResponseStream();
int l;
do
{
l = inStream.Read(buffer,0,
buffer.Length);
if(l>0)
outStream.Write(buffer,0,l);
} while(l>0);
三、多线程
我们用DocumentWorker类封装所有下载一个URL的操作。