在採集需要登陸後訪問的頁面中,採集程式需要儲存登入後擷取的cookie,由於有些網站登入驗證成功後就將使用者直接重新導向到目標頁,
如: Response.Redirect("/user/index.asp")
回應標頭部含如下參數
Location: /user/index.aspx
Set-Cookie: .ASPXAUTH=3DABFC1691FD31F16EFF68D55202130196135D8B3F0A8B630C956242FBBA802EDB912E0B84D6601A6F425824DA1C28AFBDF04E6B4D0CA6E7D7EBB7DD2A212F5FFFF2921DF35CE098F603CE31E56D71AD68CC23117123E11AB8323AD86B648665; expires=Thu, 04-Dec-2008 02:59:15 GMT; path=/; HttpOnly
這樣在使用WebClient時,不能捕捉到需要的cookie,這個時候就需要使用HttpWebRequest(WebRequest針對http協議的實現)
擷取cookieContainer
---------------------------------------
private System.Net.CookieContainer GetCookieContainer(string logUrl,byte[] data)
{
HttpWebRequest request = HttpWebRequest.Create(logUrl) as HttpWebRequest;
request.AllowAutoRedirect = false;//禁止自動重新導向
request.Method = "Post"; //使用post方法
request.ContentType = "application/x-www-form-urlencoded";//form提交時使用urlencode
request.ContentLength = data.Length;
request.CookieContainer = new CookieContainer();
Stream uploadStream=request.GetRequestStream();
uploadStream.Write(data, 0, data.Length);
uploadStream.Close();
HttpWebResponse resposne = request.GetResponse() as HttpWebResponse;
resposne.Close();
return request.CookieContainer;//反會擷取的cookieContainer
}
//登入後擷取cookie再進行資料擷取,需要導如System.IO,System.Net,System.Web等命名空間
-------------------------------------------------
string formData=@"Username=xxxx&Password=dafa34@234";//登入頁面表單欄位
//使用gb2312進行Url編碼
formData= HttpUtility.UrlEncode(formData,Encoding.GetEncoding("gb2312"));
//編碼為位元組資料
byte[] data = Encoding.GetEncoding("gb2312").GetBytes(formData);
//是需要登陸後擷取的頁面(資料擷取頁)
Uri dataUri = new Uri("http://wow52.cn/admin/article.aspx");
HttpWebRequest request = WebRequest.Create(dataUri) as HttpWebRequest;
//設定來路,有些網站會檢測訪問來路來判斷是否為盜鏈等.
//使用WebRequest時你無法直接使用 request.Hands.Add("Referer","http://www.wow52.cn/log.aspx")
//來添加標題
request.Referer="http://www.wow52.cn/log.aspx";
//一些其他設定
//request.Accept = "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-silverlight, application/x-ms-application, application/x-ms-xbap, application/vnd.ms-xpsdocument, application/xaml+xml, */*";
//request.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727)";
request.Method = "GET";
//登入頁地址,需要特別注意的是這個uri的網域名稱必須要與上面一致
//使用www.wow52.cn擷取的cookieContainer只有在網域名稱為www.wow52.cn時才會被附加上
//對一些使用了次層網域的網站,各資料頁次層網域各不相同的,可以將Cookie逐個取出
//再拼接起來,如: cookieName1=cookieValue1;cookieName2=cookieValue2;...
//將拼字後的字串添加到Request.Headers中如:request.Headers.Add("Cookie", "拼接串");
Uri logUri = new Uri("http://www.wow52.cn/log.aspx"); //這裡設定為http://www.wow52.cn/區別上面dataUri的wow52.cn
//調用上文的GetCookieContainer函數
CookieContainer container = GetCookieContainer(logUri.ToString(), data);
//判斷是否是同個網域名稱(主機名稱)
if (Uri.Compare(dataUri, logUri, UriComponents.Host, UriFormat.SafeUnescaped, StringComparison.OrdinalIgnoreCase) != 0)
{
//逐個取出cookie並更改domain後,添加到request.CookieContainer中
CookieCollection cookies = container.GetCookies(logUri);
request.CookieContainer = new CookieContainer();
foreach (Cookie cookie in cookies)
{
cookie.Domain = dataUri.Host; //使用目標資料頁的主機部分
request.CookieContainer.Add(cookie);
}
}
else //domain相同
{
request.CookieContainer = container;
}
//擷取響應資料
HttpWebResponse response = request.GetResponse() as HttpWebResponse;
StreamReader sr = new StreamReader(response.GetResponseStream(), Encoding.GetEncoding("gb2312"));
string html = sr.ReadToEnd();
response.Close();
txtMsg.Text = html; //txtMsg是文字框
---------------------------
注意,
1.上面代碼是直接從vs2005複製過來的,沒加格式化,方便於直接複製回去,
2.一般的資料擷取下使用WebClient比較方便,也可以一起使用WebClient跟WebRequest.
3.WebRequest.AllowAutoRedirect=false;屬性 來防止自動重新導向
4.WebRequest 想設定Referer 標題時使用 WebRequest.Referer="xxxx" ,直接WebRequest.Headers.Add是不行的
不過使用webClient時可以這麼做.
5.注意上面的編碼post資料一般要先進行urlEncode,並且指明
request.ContentType = "application/x-www-form-urlencoded";
webClient時使用 webClient.Headers.Add("Content-Type","application/x-www-form-urlencode");
另外在將資料轉化成byte[] data(位元組數組時)請確認網站使用的編碼是utf-8還是gb2312或其他,同樣擷取返會的資料後(指本類型的),也要根據網站的編碼進行轉化(到字串)
6.上面使用formdata是虛擬,呵呵,防止你黑了我的站(^_^),你如果要測試,請自己另外找個網站,另外.net表單提交時會有一些狀態資訊,這些你可以通過一向代理工具來擷取,並分析得出需要的post資料格式.
另外對於帶圖片驗證碼的登入,一般我們在使用WebRequest下載圖片時需要同時儲存下載圖片時的臨時SessionID(也是cookie),在提交表單時要將這個SessionID資料(cookie)附加到標題上,這樣就可以通過驗證,至於圖片識別,一般使用圖片框顯示後人工識別(通用情況下).
參考資料
HttpWebRequest