爬蟲主要用來做數據采集,又名網絡蜘蛛,內容網站很多就是用爬蟲來抓取數據的。本系列(現在還不知道有幾篇)旨在實現一個基本的爬蟲程序(框架)。開發語言:C#
爬蟲是要從源源不斷的抓取到的頁面中過濾出我需要的目標數據。既然要源源不斷的抓取數據,那么我們就要有一個各個頁面的URL的集合,去模擬訪問這些URL,來分析返回的數據,從而再根據我們分析的HTML DOM結構獲取到我們需要的數據。
URL的獲取,通常,我們應該有一個Root節點,也就是根URL,然后就像樹形結構一樣去遍歷他的各個子節點。說的形象一點,比如,一個網站的首頁,上面有各個導航的URL1、URL2,URL3……也就是說只要我們獲取到了網站首頁的數據,然后篩選出所有的URL,就能獲取這個根URL的直接子節點。然后我們再獲取URL1的數據,從而獲取URL1的直接子節點,然后一直這樣重復下去,最后我們就可以得到一個龐大的樹形結構。
數據的獲取,每請求一個URL都會返回數據,也就是HTML文檔的源碼,我們要獲取目標數據就要弄明白文檔結構,而不同的頁面有不同的文檔結構。廢話不多說了,程序員之間交流,還是直接上代碼更容易理解。
對於Http訪問,這里使用WebClient。新建一個Crawler的類庫,並且新建一個Crawler類,代碼如下:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Net; 6 using System.IO; 7 8 namespace Crawler 9 { 10 /// <summary> 11 /// 爬蟲 12 /// </summary> 13 public class Crawler 14 { 15 /// <summary> 16 /// 基URI 17 /// </summary> 18 public string BaseUri { get; set; } 19 20 /// <summary> 21 /// 構造函數 22 /// </summary> 23 /// <param name="url">基URI</param> 24 public Crawler(string baseUri) 25 { 26 this.BaseUri = baseUri; 27 } 28 29 /// <summary> 30 /// 構造函數 31 /// </summary> 32 public Crawler() { } 33 34 /// <summary> 35 /// 保存數據處理程序 36 /// </summary> 37 public Action<string> SaveHandler; 38 39 /// <summary> 40 /// 采集數據 41 /// </summary> 42 public void Crawl(string targetUri) 43 { 44 WebClient webClient = new WebClient(); 45 46 // 設置基URI 47 webClient.BaseAddress = this.BaseUri; 48 49 // 獲取流 50 StreamReader reader = new StreamReader(webClient.OpenRead(targetUri), Encoding.UTF8); 51 52 // 讀取數據 53 string html = reader.ReadToEnd(); 54 55 // 關閉流 56 reader.Close(); 57 58 // 保存結果 59 this.Save(html); 60 61 } 62 63 /// <summary> 64 /// 保存數據 65 /// </summary> 66 /// <param name="html">數據</param> 67 private void Save(string html) 68 { 69 SaveHandler(html); 70 } 71 } 72 }
這樣一個很簡單的爬蟲類就寫完了,我們可以試着調用一下,新建一個控制台應用程序,代碼如下:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using Crawler; 6 7 namespace CrawlerConsole 8 { 9 class Program 10 { 11 static void Main(string[] args) 12 { 13 14 Crawler.Crawler crawler = new Crawler.Crawler("http://www.baidu.com"); 15 16 crawler.SaveHandler = new Action<string>(html => Console.WriteLine(html)); 17 18 crawler.Crawl("/"); 19 20 } 21 } 22 }
然后我們Ctrl+F5運行一下,就可以看到我們爬到的百度首頁的源碼輸出到控制台了。
簡單介紹一下代碼中幾個需要注意的地方:
基URI:就是相對地址的主URI,我Crawl方法的參數就要要爬的地址,"/"相對於基URI"http://www.baidu.com"來說就是本頁面,也就是首頁。看MSDN的解釋,BaseAddress 屬性包含一個組合了相對地址的基 URI。調用上載或下載數據的方法時,WebClient 對象將此基 URI 與您在方法調用中指定的相對地址進行組合。如果指定的是絕對 URI,則 WebClient 不使用 BaseAddress 屬性值。若要移除以前設置的值,請將 BaseAddress 設置為 null 引用(在 Visual Basic 中為 Nothing) 或空字符串 ("")。
WebClient.OpenRead():
OpenRead 方法創建一個 Stream 實例,該實例用於讀取 address 參數指定的資源的內容。此方法在打開流時阻止。若要在等待流的同時繼續執行,請使用 OpenReadAsync方法之一。
如果 BaseAddress 屬性不是空字符串 (""),且 address 不包含絕對 URI,則 address 必須是相對 URI,此 URI 與 BaseAddress 組合在一起構成所請求數據的絕對 URI。如果QueryString 屬性不為 null 引用(在 Visual Basic 中為 Nothing),則將它追加到 address。
關於WebClient的更多信息請參照MSDN:http://msdn.microsoft.com/zh-cn/library/tt0f69eh(v=vs.100).aspx
先這樣吧,我會盡量抓緊寫后面的篇章,最近實在是忙,月底要離職了,還連加六天班。。。