程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> 構造C#語言的爬蟲蜘蛛程序(2)

構造C#語言的爬蟲蜘蛛程序(2)

編輯:關於C語言

下面來看看這兩類不同文件的存儲方式。

二進制文件的內容類型聲明不以"text/"開頭,蜘蛛程序直接把二進制文件保存到磁盤,不必進行額外的處理,這是因為二進制文件不包含HTML,因此也不會再有需要蜘蛛程序處理的Html鏈接。下面是寫入二進制文件的步驟。

首先准備一個緩沖區臨時地保存二進制文件的內容。 byte []buffer = new byte[1024];

接下來要確定文件保存到本地的路徑和名稱。如果要把一個myhost.com網站的內容下載到本地的c:test文件夾,二進制文件的網上路徑和名稱是/School/UploadFiles_7810/201206/20120601220616314.gif。與此同時,我們還要確保c:test目錄下已經創建了images子目錄。這部分任務由convertFilename方法完成。

string filename = convertFilename( response.ResponseUri );

convertFilename方法分離HTTP地址,創建相應的目錄結構。確定了輸出文件的名字和路徑之後就可以打開讀取Web頁面的輸入流、寫入本地文件的輸出流。

Stream outStream = File.Create( filename );
Stream inStream = response.GetResponseStream();

接下來就可以讀取Web文件的內容並寫入到本地文件,這可以通過一個循環方便地完成。

int l;
do
{
l = inStream.Read(buffer,0,
buffer.Length);
if(l>0)
outStream.Write(buffer,0,l);
} while(l>0);

三、多線程

我們用DocumentWorker類封裝所有下載一個URL的操作。每當一個DocumentWorker的實例被創建,它就進入循環,等待下一個要處理的URL。下面是DocumentWorker的主循環:

while(!m_spider.Quit )
{
m_uri = m_spider.ObtainWork();
  
m_spider.SpiderDone.WorkerBegin();
string page = GetPage();
if(page!=null)
ProcessPage(page);
m_spider.SpiderDone.WorkerEnd();
}

這個循環將一直運行,直至Quit標記被設置成了true(當用戶點擊"Cancel"按鈕時,Quit標記就被設置成true)。在循環之內,我們調用ObtainWork獲取一個URL。ObtainWork將一直等待,直到有一個URL可用--這要由其他線程解析文檔並尋找鏈接才能獲得。Done類利用WorkerBegin和WorkerEnd方法來確定何時整個下載操作已經完成。

從圖一可以看出,蜘蛛程序允許用戶自己確定要使用的線程數量。在實踐中,線程的最佳數量受許多因素影響。如果你的機器性能較高,或者有兩個處理器,可以設置較多的線程數量;反之,如果網絡帶寬、機器性能有限,設置太多的線程數量其實不一定能夠提高性能。

四、任務完成了嗎?

利用多個線程同時下載文件有效地提高了性能,但也帶來了線程管理方面的問題。其中最復雜的一個問題是:蜘蛛程序何時才算完成了工作?在這裡我們要借助一個專用的類Done來判斷。

首先有必要說明一下"完成工作"的具體含義。只有當系統中不存在等待下載的URL,而且所有工作線程都已經結束其處理工作時,蜘蛛程序的工作才算完成。也就是說,完成工作意味著已經沒有等待下載和正在下載的URL。

Done類提供了一個WaitDone方法,它的功能是一直等待,直到Done對象檢測到蜘蛛程序已完成工作。下面是WaitDone方法的代碼。

public void WaitDone()
{
Monitor.Enter(this);
while ( m_activeThreads>0 )
{
Monitor.Wait(this);
}
Monitor.Exit(this);
}

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved