一.流程

1. //获得二维码的qrsig,cookie标志

2. //登录二维码获得二维码的状态,及最新的url

3. //登录此网址,获得Cookies

4.//cookies,筛选出skey信息,获得post的参数

5. 提交POST

二. 代码

/// <summary>
/// 获得QQ群返回的信息
/// </summary>
/// <returns></returns>
public string GetQQGroupMessage()
{
try
{
Random random = new Random();
var da = random.NextDouble();
string qrCodeUrl = @"https://ssl.ptlogin2.qq.com/ptqrshow?appid=715030901&e=2&l=M&s=3&d=72&v=4&t=" + da.ToString() + @"&daid=73&pt_3rd_aid=0";
string qqGroupCheckUrl = null;
string qqGroupNumberUrl = @"http://qun.qq.com/cgi-bin/qun_mgr/search_group_members";
string qrsig = null;
string setCookies = null;
string postData = null;
string responseMessage = null; 
HTTPClient httpClient = new HTTPClient();

qrsig = httpClient.GetQRCode(qrCodeUrl); //获得二维码的qrsig,cookie标志

qqGroupCheckUrl = Login_QRStatu(httpClient, qrsig); //登录二维码获得二维码的状态,及最新的url

httpClient.Get(out setCookies, qqGroupCheckUrl); //登录此网址,获得Cookies

postData = GetPostData(setCookies); //cookies,筛选出skey信息,获得post的参数

responseMessage = httpClient.Post(qqGroupNumberUrl, postData);
LogHelp.LogDebug("Get QQ Group Message Success!");
return responseMessage;
}
catch (Exception ex)
{
LogHelp.LogDebug("Get QQ Group Message Failed!" + ex);
return null;
}
}

/// <summary>
/// 扫描二维码,并获得最新的url
/// </summary>
/// <param name="httpClient">
/// httpClient
/// </param>
/// <param name="qrsig">
/// qrsig
/// </param>
/// <returns></returns>
private string Login_QRStatu(HTTPClient httpClient,string qrsig)
{
int ptqrtoken = HTTPClient.HashConvert(qrsig);
string url = @"https://ssl.ptlogin2.qq.com/ptqrlogin?u1=https%3A%2F%2Fqun.qq.com%2F&ptqrtoken=" +
ptqrtoken.ToString() + 
@"&ptredirect=1&h=1&t=1&g=1&from_ui=1&ptlang=2052&action=0-1-1520572499521&js_ver=10233&js_type=1&login_sig=v-EnLBKGZcAOdXLgcH2k8Di6KrubBWgWZFpAo*KFmWVYbeWGCqLuQvlj4yanEo61&pt_uistyle=40&aid=715030901&daid=73&";
string referer = @"https://xui.ptlogin2.qq.com/cgi-bin/xlogin?appid=715030901&daid=73&pt_no_auth=1&s_url=https%3A%2F%2Fqun.qq.com%2F";
string strLogionUrl = null;
string setCookies = null;
int timeCount = 0;
while (strLogionUrl == null)
{
timeCount++;
Thread.Sleep(1000);
string dat = httpClient.Get(out setCookies, url, referer);
string[] temp = dat.Split('\'');
switch (temp[1])
{

case ("65"):
LogHelp.LogDebug("当前登录状态:二维码失效,请稍后");
break;
case ("66"):
LogHelp.LogDebug("当前登录状态:二维码有效,请扫描");
break;
case ("67"):
LogHelp.LogDebug("当前登录状态:二维码已扫描,请确认");
break;
case ("0"):
LogHelp.LogDebug("当前登录状态:确认成功,请稍候");
strLogionUrl = temp[5];
break;
default:
LogHelp.LogDebug("登录信息有误,重新扫描!");
break;
}
if(timeCount>300) //5min内有效
{
break;
}
}
return strLogionUrl;
}

/// <summary>
/// post方法的参数
/// </summary>
/// <param name="setCookie">setCookies</param>
/// <returns></returns>
private string GetPostData(string setCookie)
{
try
{
string skey = HTTPClient.GetSkey(setCookie);
//string postData = "gc=621859311&st=0&end=800&sort=0&bkn=" + HTTPClient.GetBkn(skey).ToString();
string postData = KeyWordsLibConfigManager.KeyWordsLibConfig.PostData + HTTPClient.GetBkn(skey).ToString();
return postData;
}
catch (Exception ex)
{
LogHelp.LogError("Get PostData Error!" + ex);
return null;
}
}

三. HTML解析,POST和GET方法

namespace Test.HtmlParse
{
/// <summary>
/// //网络通信相关
/// </summary>
public class HTTPClient
{


public static CookieContainer cookies = new CookieContainer();
static CookieCollection CookieCollection = new CookieCollection();
static CookieContainer CookieContainer = new CookieContainer();

/// <summary>
/// 获得response内容
/// </summary>
/// <param name="setCookies">out cookie内容</param>
/// <param name="referer"></param>
/// <param name="timeout"></param>
/// <param name="encode"></param>
/// <param name="NoProxy"></param>
/// <returns></returns>
public string Get(out string setCookies, 
string url, 
string referer = "https://xui.ptlogin2.qq.com/cgi-bin/xlogin?appid=715030901&daid=73&pt_no_auth=1&s_url=https%3A%2F%2Fqun.qq.com%2F", 
int timeout = 100000, 
Encoding encode = null, 
bool NoProxy = false)
{
if (url == null)
{
setCookies = null;
return null;
}

string dat;
HttpWebResponse res = null;
HttpWebRequest req;
try
{
req = (HttpWebRequest)WebRequest.Create(url);
req.CookieContainer = cookies;
req.AllowAutoRedirect = false;
req.Timeout = timeout;
req.Referer = referer;
if (NoProxy)
req.Proxy = null;
req.UserAgent = "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.146 Safari/537.36";
res = (HttpWebResponse)req.GetResponse();
setCookies = res.Headers.Get("Set-Cookie");
cookies.Add(res.Cookies);
}
catch (Exception ex)
{
LogHelp.LogError(string.Format("Get {0} response error! ex:{1}", url, ex));
setCookies = null;
return null;
}
StreamReader reader;
reader = new StreamReader(res.GetResponseStream(), encode == null ? Encoding.UTF8 : encode);
dat = reader.ReadToEnd();
res.Close();
req.Abort();
LogHelp.LogDebug(string.Format("Get Method request succeed! - setCookies={0},url ={1}", setCookies, url));
return dat;
}

/// <summary>
/// QR二维码,返回qrsig值
/// </summary>
/// <param name="url"></param>
/// <param name="referer"></param>
/// <param name="timeout"></param>
/// <param name="encode"></param>
/// <param name="NoProxy"></param>
public string GetQRCode(
string url, 
string referer = "https://xui.ptlogin2.qq.com/cgi-bin/xlogin?appid=715030901&daid=73&pt_no_auth=1&s_url=https%3A%2F%2Fqun.qq.com%2F", 
int timeout = 100000, 
Encoding encode = null, 
bool NoProxy = false)
{
if (url == null)
return null;

string qrsigCookie = null;
HttpWebResponse res = null;
HttpWebRequest req;
try
{
req = (HttpWebRequest)WebRequest.Create(url);
req.CookieContainer = cookies;
req.AllowAutoRedirect = false;
req.Timeout = timeout;
req.Referer = referer;
if (NoProxy)
req.Proxy = null;
req.UserAgent = "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.146 Safari/537.36";
res = (HttpWebResponse)req.GetResponse();
cookies.Add(res.Cookies);
}
catch (Exception ex)
{
LogHelp.LogError(string.Format("GetQR {0} response error! ex:{1} ", url, ex));
throw ex;
}
try
{
StreamReader reader;
reader = new StreamReader(res.GetResponseStream(), encode == null ? Encoding.UTF8 : encode);
Bitmap bmap = new Bitmap(res.GetResponseStream());
bmap.Save(@"D:\QRCode.jpg");
//发送邮件
string title = "QQ群登录二维码";
string content = "请在五分钟内扫描登录二维码,过期失效!";
string[] receiveAddrs = KeyWordsLibConfigManager.KeyWordsLibConfig.EmailAddrs.ReceiveAddr.ToArray();
string[] attachAddrs = KeyWordsLibConfigManager.KeyWordsLibConfig.EmailAddrs.AttachUri.ToArray();
EmailPack pack = new EmailPack(title, content, receiveAddrs, null, attachAddrs);
LogHelp.LogInfo(this, "收到邮件发送请求Title:" + title + ",receiveAddrs:" + string.Join(",", receiveAddrs));
pack.Send();

qrsigCookie = res.Headers.Get("set-cookie");
if (qrsigCookie == null)
{
return null;
}
var index1 = qrsigCookie.IndexOf("=");
var index2 = qrsigCookie.IndexOf(";");
qrsigCookie = qrsigCookie.Substring(index1 + 1, 64);
res.Close();
req.Abort();
LogHelp.LogInfo(string.Format("GetQRCode Method request succeed! - qrsigCookie={0},url ={1}", qrsigCookie, url));
return qrsigCookie;
}
catch (Exception ex)
{
LogHelp.LogError("qrsigCookie error or reader wrong! ex:" + ex);
throw ex;
}
}

/// <summary>
/// Post方法
/// </summary>
/// <param name="url">url</param>
/// <param name="postData">post-data </param>
/// <param name="Referer"></param>
/// <param name="timeout"></param>
/// <param name="encode"></param>
/// <returns> reponse content </returns>
internal string Post(
string url, 
string postData, 
string Referer = "//qun.qq.com/member.html#gid=621859311", 
int timeout = 100000, 
Encoding encode = null)
{
if (url == null)
return null;
string dat = "";
HttpWebRequest req;
try
{
req = WebRequest.Create(url) as HttpWebRequest;
req.CookieContainer = cookies;
req.ContentType = "application/x-www-form-urlencoded";
req.Method = "POST";
req.Proxy = null;
req.Timeout = timeout;
req.UserAgent = "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.146 Safari/537.36";
req.ProtocolVersion = HttpVersion.Version10;
req.Referer = Referer;

byte[] mybyte = Encoding.Default.GetBytes(postData);
req.ContentLength = mybyte.Length;
Stream stream = req.GetRequestStream();
stream.Write(mybyte, 0, mybyte.Length);
HttpWebResponse res = req.GetResponse() as HttpWebResponse;
cookies.Add(res.Cookies);
stream.Close();
StreamReader SR = new StreamReader(res.GetResponseStream(), encode == null ? Encoding.UTF8 : encode);
dat = SR.ReadToEnd();
res.Close();
req.Abort();
LogHelp.LogDebug(string.Format("Post Method request succeed! - postData={0},url ={1}", postData, url));
}
catch (Exception ex)
{
LogHelp.LogError(string.Format("Post Method error! ex:{0}", ex));
return null;
}
return dat;
}

/// <summary>
/// bkn 解密方法
/// </summary>
/// <param name="skey"></param>
/// <returns></returns>
public static long GetBkn(string skey)
{
var hash = 5381;
for (int i = 0, len = skey.Length; i < len; ++i)
{
hash += (hash << 5) + (int)skey[i];
}
return hash & 2147483647;
}

/// <summary>
/// Get skey string
/// </summary>
/// <param name="setCookie"></param>
/// <returns></returns>
public static string GetSkey(string setCookie)
{
if (setCookie == null)
return null;
string cookieTemp = Regex.Replace(setCookie, @"p_skey", "");
string[] cookies = cookieTemp.Split(';');
string skey = null;
foreach (var c in cookies)
{
if (c.Contains("skey"))
{
int index = c.IndexOf("=");
skey = c.Substring(index + 1);
break;
}
}
return skey;
}

/// <summary>
/// 哈希转换, for qrtoken
/// </summary>
/// <param name="cookie"></param>
/// <returns></returns>
public static int HashConvert(string cookie)
{
int e = 0;
for (int j = 0, k = cookie.Length; k > j; j++)
{
char temp = cookie.ElementAt(j);
e += (e << 5) + Convert.ToByte(temp);
}
return 2147483647 & e;
}

}
}