使用C#的HttpWebRequest模拟登陆访问人人网

无论使用任何语言做模拟登陆或者抓取访问页面,无外乎以下思路:
第一 启用一个web访问会话方法或者实例化一个web访问类,如.net中的HttpWebRequest;
第二 模拟POST或者GET方式提交的数据;
第三 模拟请求的头;
第四 提交请求并获得响应,及对响应做我们所需要的处理。
这里我们以人人网的登录为例,将涉及到POST以及GET两种请求方式。
在之前的文章《免费网页抓包工具,火狐插件FireBug的抓包使用教程》中我们知道,登陆人人网的时候,一共做了一个POST请求以及两个GET请求,如下图:

人人网登录请求

观察这三个请求的详细信息,不难看出第一个GET请求的地址可以由POST的响应得到,而第二个GET请求的地址又由第一个GET的响应得到。
先来模拟第一个POST请求

  1. HttpWebRequest request = null;   
  2. HttpWebResponse response = null;   
  3. string gethost = string.Empty;   
  4. CookieContainer cc = new CookieContainer();   
  5. string Cookiesstr = string.Empty;   
  6. try  
  7. {   
  8.         //第一次POST请求   
  9.     string postdata = "email=" + UserName.Replace("@""%40") + "&password=" + PassWord + "&origURL=" + HostUrl + "&domain=renren.com";//模拟请求数据,数据样式可以用FireBug插件得到。人人网POST数据时,用户名邮箱中的“@”变为“%40”,所以我们也要作此变化   
  10.     string  LoginUrl="http://www.renren.com/PLogin.do";   
  11.       request = (HttpWebRequest)WebRequest.Create(LoginUrl);//实例化web访问类   
  12.     request.Method = "POST";//数据提交方式为POST   
  13.       //模拟头   
  14.     request.ContentType = "application/x-www-form-urlencoded";   
  15.       byte[] postdatabytes = Encoding.UTF8.GetBytes(postdata);   
  16.       request.ContentLength = postdatabytes.Length;   
  17.       //request.Referer = "http://www.renren.com/Login.do?rf=r&domain=renren.com&origURL=" + HostUrl;   
  18.       request.AllowAutoRedirect = false;   
  19.       request.CookieContainer = cc;   
  20.       request.KeepAlive = true;   
  21.       //提交请求   
  22.     Stream stream;   
  23.       stream = request.GetRequestStream();   
  24.       stream.Write(postdatabytes, 0, postdatabytes.Length);   
  25.       stream.Close();   
  26.       //接收响应   
  27.     response = (HttpWebResponse)request.GetResponse();   
  28.       //保存返回cookie   
  29.       response.Cookies = request.CookieContainer.GetCookies(request.RequestUri);   
  30.       CookieCollection cook = response.Cookies;   
  31.       string strcrook = request.CookieContainer.GetCookieHeader(request.RequestUri);   
  32.       Cookiesstr = strcrook;   
  33.       //取第一次GET跳转地址   
  34.     StreamReader sr = new StreamReader(response.GetResponseStream(), Encoding.UTF8);   
  35.       string content = sr.ReadToEnd();   
  36.       response.Close();   
  37.       string[] substr = content.Split(new char[] { '"' });   
  38.       gethost = substr[1];   
  39. }   
  40. catch (Exception)   
  41. {   
  42.       //第一次POST出错;   
  43. }  
HttpWebRequest request = null;
HttpWebResponse response = null;
string gethost = string.Empty;
CookieContainer cc = new CookieContainer();
string Cookiesstr = string.Empty;
try
{
        //第一次POST请求
    string postdata = "email=" + UserName.Replace("@", "%40") + "&password=" + PassWord + "&origURL=" + HostUrl + "&domain=renren.com";//模拟请求数据,数据样式可以用FireBug插件得到。人人网POST数据时,用户名邮箱中的“@”变为“%40”,所以我们也要作此变化
    string  LoginUrl="http://www.renren.com/PLogin.do";
      request = (HttpWebRequest)WebRequest.Create(LoginUrl);//实例化web访问类
    request.Method = "POST";//数据提交方式为POST
      //模拟头
    request.ContentType = "application/x-www-form-urlencoded";
      byte[] postdatabytes = Encoding.UTF8.GetBytes(postdata);
      request.ContentLength = postdatabytes.Length;
      //request.Referer = "http://www.renren.com/Login.do?rf=r&domain=renren.com&origURL=" + HostUrl;
      request.AllowAutoRedirect = false;
      request.CookieContainer = cc;
      request.KeepAlive = true;
      //提交请求
    Stream stream;
      stream = request.GetRequestStream();
      stream.Write(postdatabytes, 0, postdatabytes.Length);
      stream.Close();
      //接收响应
    response = (HttpWebResponse)request.GetResponse();
      //保存返回cookie
      response.Cookies = request.CookieContainer.GetCookies(request.RequestUri);
      CookieCollection cook = response.Cookies;
      string strcrook = request.CookieContainer.GetCookieHeader(request.RequestUri);
      Cookiesstr = strcrook;
      //取第一次GET跳转地址
    StreamReader sr = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
      string content = sr.ReadToEnd();
      response.Close();
      string[] substr = content.Split(new char[] { '"' });
      gethost = substr[1];
}
catch (Exception)
{
      //第一次POST出错;
}

注释写的很详细了,在这就不再分析,也许有人对request = (HttpWebRequest)WebRequest.Create(LoginUrl)有疑问,可以去google一下HttpWebRequest和WebRequest的区别,简单来说WebRequest是一个抽象类,不能直接实例化,需要被继承,而HttpWebRequest继承自WebRequest。

再模拟第一个和第二个GET请求

  1. try  
  2. {   
  3.     request = (HttpWebRequest)WebRequest.Create(gethost);   
  4.     request.Method = "GET";   
  5.     request.KeepAlive = true;   
  6.     request.Headers.Add("Cookie:" + Cookiesstr);   
  7.     request.CookieContainer = cc;   
  8.     request.AllowAutoRedirect = false;   
  9.     response = (HttpWebResponse)request.GetResponse();   
  10.     //设置cookie   
  11.     Cookiesstr = request.CookieContainer.GetCookieHeader(request.RequestUri);   
  12.     //取再次跳转链接   
  13.     StreamReader sr = new StreamReader(response.GetResponseStream(), Encoding.UTF8);   
  14.     string ss = sr.ReadToEnd();   
  15.     string[] substr = ss.Split(new char[] { '"' });   
  16.     gethost = substr[1];   
  17.     request.Abort();   
  18.     sr.Close();   
  19.     response.Close();   
  20. }   
  21. catch (Exception)   
  22. {   
  23.     //第一次GET出错   
  24. }   
  25. try  
  26. {   
  27.     //第二次GET请求   
  28.     request = (HttpWebRequest)WebRequest.Create(gethost);   
  29.     request.Method = "GET";  
  30.     request.KeepAlive = true;  
  31.     request.Headers.Add("Cookie:" + Cookiesstr);   
  32.     request.CookieContainer = cc;   
  33.     request.AllowAutoRedirect = false;   
  34.     response = (HttpWebResponse)request.GetResponse();   
  35.     //设置cookie   
  36.     Cookiesstr = request.CookieContainer.GetCookieHeader(request.RequestUri);   
  37.     request.Abort();   
  38.     response.Close();   
  39. }   
  40. catch (Exception)   
  41. {   
  42.     //第二次GET出错   
  43. }  
try
{
	request = (HttpWebRequest)WebRequest.Create(gethost);
	request.Method = "GET";
	request.KeepAlive = true;
	request.Headers.Add("Cookie:" + Cookiesstr);
	request.CookieContainer = cc;
	request.AllowAutoRedirect = false;
	response = (HttpWebResponse)request.GetResponse();
	//设置cookie
	Cookiesstr = request.CookieContainer.GetCookieHeader(request.RequestUri);
	//取再次跳转链接
	StreamReader sr = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
	string ss = sr.ReadToEnd();
	string[] substr = ss.Split(new char[] { '"' });
	gethost = substr[1];
	request.Abort();
	sr.Close();
	response.Close();
}
catch (Exception)
{
	//第一次GET出错
}
try
{
	//第二次GET请求
	request = (HttpWebRequest)WebRequest.Create(gethost);
	request.Method = "GET";
	request.KeepAlive = true;
	request.Headers.Add("Cookie:" + Cookiesstr);
	request.CookieContainer = cc;
	request.AllowAutoRedirect = false;
	response = (HttpWebResponse)request.GetResponse();
	//设置cookie
	Cookiesstr = request.CookieContainer.GetCookieHeader(request.RequestUri);
	request.Abort();
	response.Close();
}
catch (Exception)
{
	//第二次GET出错
}

GET与POST请求大同小异,这里便不再累述。三次请求结束,保存好你的cookie string,每次请求的时候都赋给请求的头部,你就处于登录状态了。
人人网的HttpWebRequest登陆模拟很简单,但是POST及GET涉及到了,是个不错的案例。
当然,在.net想做自动访问的操作还可以使用WebBrowser控件,而且还能够和HttpWebRequest共用cookie,抛砖引玉一下不在本篇文章的讨论范围。

posted @ 2012-03-14 16:12  郑文亮  阅读(4696)  评论(1编辑  收藏  举报