前段時間上了某論壇的技術討論區,習慣性的打開搜索看有沒有我需要的內容,一登陸賬號,發現自己被禁言了,連基本的搜索功能也被限制了。無奈只能手動的一個一個會找帖子。我去,竟然有200多頁,每頁有40第數據,這樣純手工的方式實在是太蛋疼了。
前段時間自己不是寫了一個小爬蟲嗎?於是我的個人論壇搜索器開始構建了。
一,整體構建
二,實際編碼
1,數據讀取編碼:
讀取網頁有很多種方法,第一讀取網頁我選擇的是最簡單的方式
static string GetPage(int page)
{
string reuslt = string.Empty;
System.Net.WebClient wb = new System.Net.WebClient();
reuslt = wb.DownloadString("http://xx.xxx.xx/thread0806.php?fid=7&search=&page=" + page);
return reuslt;
}
直接利用webclient 讀取內容:
咦,這是怎么回事?
直接訪問是不可以的,哪里出錯了呢?
難不成是地址出錯了?我重新檢查了一次沒有拼錯,那換成其它地址呢?
測試可以使用,那就是說這種請求方式只對百度有效。
那說明:直接使用webClinent類來請求xx.xxx.xx這種網站是不可行的,因為它會來接收你的請求頭的信息來判斷是人工發出的請求還是非人工發出的請求。
如何構造請求頭是關鍵!
那換用另一種方式來請求來,如果要構建新的請求方式,那首先要明白,一次“人工的請求方式”應該是怎么樣的,打開chrome,監視了一次請求,得到結果如下:
一次合理的請求方式包含哪些信息呢?
url:請求地址
Method:請求方式
Headers:
Accept:本次請求得到的回應的數據格式,版本
Accept-Charset:我這次請求可以接受的編碼格式 GBK,UTF-8;q=0.7
Accept-Encoding:編碼格式(gzip格式)
Accept-Language:中文
Cache-Control:緩存設置
User-Agent:請求標識頭部分
OK,這些既然得到了,那可以開始構建一次正常的請求了。
static string Getpage(int page) { System.IO.Stream response; System.IO.StreamReader sr; string result = string.Empty; string domain = "http://xx.xxx.xx/thread0806.php?fid=7&search=&page=" + page; HttpWebRequest request = (HttpWebRequest)WebRequest.Create(domain); request.Method = "GET"; request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"; request.Headers.Set("Accept-Charset", "GBK,utf-8;q=0.7,*;q=0.3"); request.Headers.Set("Accept-Language", "zh-cn,zh;q=0.5"); request.Headers.Set("Accept-Encoding", "gzip,deflate,sdch"); request.Host = "xx.xxx.xx"; request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.47 Safari/536.11"; request.KeepAlive = true; HttpWebResponse httprp = (HttpWebResponse)request.GetResponse(); httprp.Headers.Set("Content-Encoding", "gzip"); response = httprp.GetResponseStream(); sr = new System.IO.StreamReader(response,Encoding.UTF8); result = sr.ReadToEnd(); response.Close(); sr.Close(); return result; }
OK,那測試一下看得到數據沒有.
怎么都是亂碼呢?
設置讀取的時候都是正常的UTF-8編碼,如果讀取的編碼沒有問題,那問題應該出在傳送的編碼上面。我竟然忽略了返回的格式了
httprp.Headers.Set("Content-Encoding", "gzip");
很明顯,文檔經過了Gzip格式進行壓縮,然后在傳送過來了,那需要解碼一次:代碼如下
static string Getpage(int page) { System.IO.Stream response; System.IO.StreamReader sr; string result = string.Empty; string domain = "http://xx.xxx.xx/thread0806.php?fid=7&search=&page=" + page; HttpWebRequest request = (HttpWebRequest)WebRequest.Create(domain); request.Method = "GET"; request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"; request.Headers.Set("Accept-Charset", "GBK,utf-8;q=0.7,*;q=0.3"); request.Headers.Set("Accept-Language", "zh-cn,zh;q=0.5"); request.Headers.Set("Accept-Encoding", "gzip,deflate,sdch"); request.Host = "xx.xxx.xx"; request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.47 Safari/536.11"; request.KeepAlive = true; HttpWebResponse httprp = (HttpWebResponse)request.GetResponse(); httprp.Headers.Set("Content-Encoding", "gzip"); response = httprp.GetResponseStream();
//重新修改后的代碼 sr = new System.IO.StreamReader(new GZipStream(response, CompressionMode.Decompress), Encoding.GetEncoding("gb2312")); result = sr.ReadToEnd(); response.Close(); sr.Close(); return result; }
那得到結果沒有呢?
OK,正常得到結果!那下面的工作就簡單了~
PS:晚上繼續更新第二部分,(數據展示內容---正則表達式的應用)