1.通过chrome或firefox等工具的NetWork面板,跟踪到请求过程中传递的 Request Headers。
2.将Request Headers 附加到请求,DoRequest的headers参数。
3.通过chrome或firefox等工具的NetWork面板,跟踪到请求过程中传递的 Form Data。
4.将Form Data 附加到请求中,DoRequest的content参数。
5.请求成功后,将HttpResponseHeader.SetCookie记录到CookieDic集合。
6.下次请求时,附加上第3步的CookieDic集合,即可模拟登录后操作。
封装代码
using System; using System.Collections.Generic; using System.IO; using System.IO.Compression; using System.Linq; using System.Net; using System.Text; using System.Text.RegularExpressions; namespace RC.Software.Travel { /// <summary> /// Http请求封装类,用于模拟登录等操作 /// 工作原理: /// 1.通过chrome的NetWork面板,跟踪到请求过程中传递的 Request Headers /// 2.将Request Headers 附加到请求。 /// 3.请求成功后,将HttpResponseHeader.SetCookie记录下来。 /// 4.下次请求时,附加上第3步的cookie,即可模拟登录后操作。 /// </summary> public class HttpRequestHelper { /// <summary> /// cookie集合,用于模拟登陆 /// </summary> private static readonly Dictionary<string, Cookie> CookieDic = new Dictionary<string, Cookie>(); /// <summary> /// Http请求 /// </summary> /// <param name="url"></param> /// <param name="method"></param> /// <param name="headers"></param> /// <param name="content"></param> /// <returns></returns> public static string DoRequest(string url, string method, string headers, string content) { var request = (HttpWebRequest)WebRequest.Create(url); request.Method = method; if (method.Equals("GET", StringComparison.InvariantCultureIgnoreCase)) { request.MaximumAutomaticRedirections = 100; request.AllowAutoRedirect = false; } #region 1.设置Http头部 if (!string.IsNullOrWhiteSpace(headers)) { var hsplit = headers.Split(new[] { "\n" }, StringSplitOptions.RemoveEmptyEntries); foreach (var item in hsplit) if (!item.StartsWith(":")) { var kv = item.Split(':'); if (kv.Length == 2) { var key = kv[0].Trim(); var value = string.Join(":", kv.Skip(1)).Trim(); #region 设置http头 switch (key.ToLower()) { case "accept": { request.Accept = value; break; } case "host": { request.Host = value; break; } case "connection": { if (value == "keep-alive") request.KeepAlive = true; else request.KeepAlive = false; //just test break; } case "content-type": { request.ContentType = value; break; } case "user-agent": { request.UserAgent = value; break; } case "referer": { request.Referer = value; break; } case "content-length": { request.ContentLength = Convert.ToInt64(value); break; } case "expect": { request.Expect = value; break; } case "if-modified-since": { request.IfModifiedSince = Convert.ToDateTime(value); break; } case "cookie": { var cc = new CookieCollection(); var cookieString = value; if (!string.IsNullOrWhiteSpace(cookieString)) { var spilit = cookieString.Split(';'); foreach (var ci in spilit) { var arr = ci.Split('='); if (kv.Length == 2) cc.Add(new Cookie(arr[0].Trim(), arr[1].Trim())); } } } break; } #endregion } } } #endregion #region 2.设置cookie request.Headers[HttpRequestHeader.Cookie] = GetCookieStr(); #endregion #region 3.发送请求数据 if (!string.IsNullOrWhiteSpace(content)) { var data = Encoding.UTF8.GetBytes(content); request.ContentLength = data.Length; using (var stream = request.GetRequestStream()) { stream.Write(data, 0, data.Length); stream.Close(); } } #endregion var response = (HttpWebResponse)request.GetResponse(); #region 4.保存cookie,用于下次请求 var cookies = new CookieCollection(); var s = response.Headers[HttpResponseHeader.SetCookie].Replace("HttpOnly,", "").Replace("httponly,", ""); if (!string.IsNullOrWhiteSpace(s)) { var spilit = s.Split(';'); foreach (var item in spilit) { var kv = item.Split('='); if (kv.Length == 2) cookies.Add(new Cookie(kv[0].Trim(), kv[1].Trim())); } } foreach (Cookie c in cookies) if (CookieDic.ContainsKey(c.Name)) CookieDic[c.Name] = c; else CookieDic.Add(c.Name, c); #endregion var result = GetResponse(response); return Unicode2String(result); } /// <summary> /// 将Unicode转换为中文 /// </summary> /// <param name="source"></param> /// <returns></returns> public static string Unicode2String(string source) { return new Regex(@"\\u([0-9A-F]{4})", RegexOptions.IgnoreCase).Replace( source, x => string.Empty + Convert.ToChar(Convert.ToUInt16(x.Result("$1"), 16))); } /// <summary> /// 从HttpWebResponse读取响应文本 /// </summary> /// <param name="response"></param> /// <returns></returns> private static string GetResponse(HttpWebResponse response) { var defaultEncode = Encoding.UTF8; var contentType = response.ContentType; if (contentType.ToLower().Contains("gb2312")) defaultEncode = Encoding.GetEncoding("gb2312"); else if (contentType.ToLower().Contains("gbk")) defaultEncode = Encoding.GetEncoding("gbk"); else if (contentType.ToLower().Contains("zh-cn")) defaultEncode = Encoding.GetEncoding("zh-cn"); string responseBody; if (response.ContentEncoding.ToLower().Contains("gzip")) using (var stream = new GZipStream(response.GetResponseStream(), CompressionMode.Decompress)) { using (var reader = new StreamReader(stream)) { responseBody = reader.ReadToEnd(); } } else if (response.ContentEncoding.ToLower().Contains("deflate")) using (var stream = new DeflateStream(response.GetResponseStream(), CompressionMode.Decompress)) { using (var reader = new StreamReader(stream, defaultEncode)) { responseBody = reader.ReadToEnd(); } } else using (var stream = response.GetResponseStream()) { using (var reader = new StreamReader(stream, defaultEncode)) { responseBody = reader.ReadToEnd(); } } return responseBody; } private static string GetCookieStr() { var sb = new StringBuilder(); foreach (var item in CookieDic) if (!item.Value.Expired) { if (sb.Length == 0) sb.Append(item.Key).Append("=").Append(item.Value.Value); else sb.Append("; ").Append(item.Key).Append(" = ").Append(item.Value.Value); } return sb.ToString(); } } }