程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> 關於C# >> c#實現QQ群成員列表導出及郵件群發之群列表及群成員獲取

c#實現QQ群成員列表導出及郵件群發之群列表及群成員獲取

編輯:關於C#

前言

通過前兩篇的代碼編寫已經能正常模擬QQ登陸,拿到cookie也就是我們進行以後相關操作的金 鑰匙。這篇文章將通過代碼的方式去獲取登陸QQ賬號的群列表,某群裡面的群成員列表。

本文重點:

1、抓包獲取QQ群列表訪問地址

2、抓包獲取QQ群成員列表

3、參數值計算,gtk的計算 方法(網上幾乎找不到的計算方法)

4、處理返回值

本文完成這一系列也基本算是完成了,到此 篇為止,可正常獲取群成員,當然也就是拿到了QQ郵箱,如果想進行其他操作的話,同樣也可以用次方式來實 現。

抓包

1、獲取QQ群列表

首先我們用登陸成功的QQ去訪問我們的群空間,群空間的頭 部有我的群,在此我們可以看到登陸QQ上面所有的群列表,也就是說此頁面必有返回該列表的請求地址,做 web開發的大體都差不多,這種東西多用Js處理,相信我們也可以抓到此地址,如下圖所示。

相比而言這個地方的抓包不需要挨個去看了,這次給的JS請求地址很直觀通過名字我們一眼就可以看出是 群列表,在抓包過程中我們會發現有一條get_group_list的地址,不用說這個就是了,查看這個js返回的數據 剛好便是群列表,如下圖

右側group便是登陸QQ上所有的qq群,包含總數目等信息。

相關請求地址:

http://qun.qzone.qq.com/cgi-bin/get_group_list?uin={0}&ua=Mozilla%2F5.0%20(Windows% 20NT%206.1%3B

%20WOW64)%20AppleWebKit%2F537.36%20(KHTML%2C%20like%20Gecko)%20Chrome% 2F28.0.1500.95%20Safari

%2F537.36&random={1}&g_tk={2}

參數0:賬號,參數1:隨即數 ,參數2:此次訪問的gtk值

2、獲取訪問群空間的成員列表

訪問具體群空間,在群空間右側有 群成員選項,選擇以後變回返回所有的群成員,如圖

在點擊群成員列表的時候我們通過抓包工具可抓起返回數據的地址,這個也很明顯,很直觀 get_group_member,一看便知是返回群成員,查看返回的數據,下面給出fiddler和谷歌浏覽器返回的數據格 式

請求地址:

http://qun.qzone.qq.com/cgi-bin/get_group_member?

uin={0}&groupid= {2}&random={3}&g_tk={4}

參數0:賬號,參數1:群號,參數2:隨即數,參數3:此次訪問的 gtk值

代碼部分

1、gtk參數的計算(此參數的計算方法幾乎沒有)

通過上述抓包我們看到 ,數據包主體部分最後一個參數就是g_tk值,一般是一串數字。那這個值到底怎麼算出來的呢?因為我們在網 頁登錄QQ的時候,騰訊都會通過cookies裡的skey值來計算,用js來算。既然在運算的時候執行了js腳本,那 麼我們就可以在抓包中獲得。那g_tk是通過什麼算法算出來的?其實很簡單,當我們得到skey後,循環取單字 符的二進制並取左值.累加之後就得到後面的g_tk值了,這聽上去很復雜,不過算法不用我們自己寫,我們只 需要執行在騰訊網頁登錄的時候所執行的那個js腳本就可以了。在這裡我已經將此算法轉化成c#代碼:

/// <summary>
        /// 計算gtk
        /// </summary>
        /// <returns></returns>
        public static Int32 GetGTK(List<Cookie> cookies)
        {
            int gtk = 0;
            foreach (var item in cookies)
            {
                if (item.Name == "skey")
                {
                    int hash = 5381;
                    string str = item.Value;
                    for (int i = 0, len = str.Length; i < len; ++i)
                    {
                        hash += (hash << 5) + str.ElementAt(i);
                    }
                    gtk = hash & 0x7fffffff;
                }
            }
            return gtk;
        }

同時也給出一個遍歷CookieContainer的方法:

/// <summary>
        /// 遍歷CookieContainer
        /// </summary>
        /// <param name="cc"></param>
        /// <returns></returns>
        public static List<Cookie> GetAllCookies(CookieContainer cc)
        {
            List<Cookie> lstCookies = new List<Cookie>();
     
            Hashtable table = (Hashtable)cc.GetType().InvokeMember("m_domainTable",
                System.Reflection.BindingFlags.NonPublic | 

System.Reflection.BindingFlags.GetField |
                System.Reflection.BindingFlags.Instance, null, cc, new object[] { });
     
            foreach (object pathList in table.Values)
            {
                SortedList lstCookieCol = (SortedList)pathList.GetType().InvokeMember("m_list",
                    System.Reflection.BindingFlags.NonPublic | 

System.Reflection.BindingFlags.GetField
                    | System.Reflection.BindingFlags.Instance, null, pathList, new object[] { 

});
                foreach (CookieCollection colCookies in lstCookieCol.Values)
                    foreach (Cookie c in colCookies) lstCookies.Add(c);
            }
            return lstCookies;
        }

唯一一個重要的參數解決以後便是請求地址,返回數據了,收獲果實的時候了。

2 、獲取群列表

下面先寫兩個處理返回Json字符串的方法,本文沒有用第三方的處理工具,二是用.net 3.5以後出現的System.Web.Extensions.dll中提供的序列化方法實現。

//json解析群列表
    public class QQGropJson
    {
        public int code { get; set; }
        public int defaults { get; set; }
        public QQGrouplist data { get; set; }
        public string message { get; set; }
        public int subcode { get; set; }
    }
    public class QQGroupInfo
    {
        public int count { get; set; }
        public int flag { get; set; }
        public string groupid { get; set; }
        public string groupname { get; set; }
    }
    public class QQGrouplist
    {
        public List<QQGroupInfo> group { get; set; }
        public int guid { get; set; }
        public int total { get; set; }
    }
    //以下三個類解析群成員
    public class QQMember
    {
        public string iscreator { get; set; }
        public string ismanager { get; set; }
        public string nick { get; set; }
        public string uin { get; set; }
    }
    public class QQGroup
    {
        public int code { get; set; }
        public int subcode { get; set; }
        public string message { get; set; }
        public int defaults { get; set; }
        public QQInfo data { get; set; }
        public int level { get; set; }
        public string nick { get; set; }
        public int option { get; set; }
        public int total { get; set; }
    }
    public class QQInfo
    {
        public int alpha { set; get; }
        public int bbscount { get; set; }
        public int classs { get; set; }
        public string createtime { get; set; }
        public int filecount { get; set; }
        public string fingermemo { get; set; }
        public string groupmemo { get; set; }
        public string groupname { get; set; }
        public List<QQMember> item { get; set; }
    }

過濾返回的_callback標簽:

/// <summary>
        /// 過濾返回的標簽_callback();
        /// </summary>
        /// <param name="retstr"></param>
        /// <returns></returns>
        public static string FilterReturnstring(string retstr)
        {
            string result = retstr.Substring(10, retstr.Length - 12);
            return result;
        }

解析返回的json數據

//解析json字符串返回群信息
        public static List<QQGroupInfo> GetGropList(string jsonstring)
        {
            var js = new JavaScriptSerializer();
            QQGropJson grouplist = new QQGropJson();
            grouplist = js.Deserialize<QQGropJson>(jsonstring);
            return grouplist.data.group;
        }

獲取群列表

var list = HttpHelper.GetAllCookies(_cookie);
            string gtk = HttpHelper.GetGTK(list).ToString();
            ////群列表
            string grouplisturl = string.Format(@"http://qun.qzone.qq.com/cgi-

bin/get_group_list?uin={0}&random={1}&g_tk={2}",usernum,rand.NextDouble(),gtk);
            string tmp = HttpHelper.GetHtml(grouplisturl, _cookie);
            List<QQGroupInfo> grouplist = HttpHelper.GetGropList

(HttpHelper.FilterReturnstring(tmp));

解析群成員列表json的方法

/// 

<summary>
        /// 群成員列表
        /// </summary>
        /// <param name="jsonstring"></param>
        /// <returns></returns>
        public static List<QQMember> GetMemberList(string jsonstring)
        {
            var js = new JavaScriptSerializer();
            QQGroup group = new QQGroup();
            group = js.Deserialize<QQGroup>(jsonstring);
            return group.data.item;
        }

以上方法grouplist便是群列表賬號

獲取某一群的成員列表

////群成員
            var list = HttpHelper.GetAllCookies(_cookie);
            string gtk = HttpHelper.GetGTK(list).ToString();
            string groupnumber = this.cmbQQgroup.SelectedValue.ToString();
            string groupmemberlist = string.Format(@"http://qun.qzone.qq.com/cgi-

bin/get_group_member?uin={0}&groupid={1}&random={2}&g_tk={3}", usernum, 

groupnumber,rand.NextDouble(),gtk);
            string tmp = HttpHelper.GetHtml(groupmemberlist, _cookie);
            grouplist = HttpHelper.GetMemberList(HttpHelper.FilterReturnstring(tmp));//成員列表

文章到此,群成員拿到了,同時也拿到了QQ郵箱。

結語

本文的重點在於拿著cooke這 把鑰匙去開門,相對比較簡單,唯一一個比較難的就是gtk參數的計算方法,這個在QQ空間對日志等操作的時 候是必不可少的參數。

時間倉促,代碼及文章比較雜亂,有什麼出錯的地方歡迎指出。若資料有用, 幫忙頂一下。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved