[c#] 網絡協議模擬之QQ微博分享接口應用


      QQ微博在營銷領域越來越受青睞了,這里面集成了很多非常有用的接口,像是郵件分享、空間分享、QQ分享、微信分享等。這相對於傳統的直接模擬協議,登錄郵箱等方式進行郵件發送甚至更有效。所有這些都沒什么技術難度,所以實現起來是很簡單的。如果在開發過程中遇到了些困難的話,可能是多線程的把握吧!

     在這樣一些營銷類項目之中,絕大多數都設計了多賬號切換操作,這使得整個架構控制起來異常繁瑣。對於多線程功底稍差的人來說,加上UI設計的搭配,簡直就是地獄般的折磨。項目實戰開發最需要的就是經驗的積累,平時練習的時候就得多為下一次開發做技術上的准備,否則一旦開始就會顯得很吃力耗時。

    

上圖只是我一個項目里的一張截圖,我們要說的功能大致就是上面圖中所表現出來的。但是這里,只做一個功能實現描述,不作項目完整實現。

步驟:

1.基礎功能的類准備

1.處理xml的xmlHelper,2.處理Http模擬的HttpHelper 3.處理QQ登錄驗證密碼MD5加密的QQMd5 4.其他一些Util功能實現類

所有這些類我會稍后放在文章附件里。

2.創建Account用戶資料類[登錄]

下面的這個類我只是給各位一個例子,可以展開看一下,但是還是要自己依據自己情況具體分析。

View Code
public class Account
   {
       #region 屬性
       /// <summary>
       /// 帳號登錄的順序號碼
       /// </summary>
       public int ID { get; set; }
       /// <summary>
       /// QQ帳號
       /// </summary>
       public string Uin { get; set; }
       public List<string> Froms { get; set; }
       public string Mail { get; set; }
       /// <summary>
       /// 昵稱
       /// </summary>
       public string Nick { get; set; }
       /// <summary>
       /// 我的首頁
       /// </summary>
       public string MyPage { get; set; }
       /// <summary>
       /// QQ未加密的密碼
       /// </summary>
       public string Password { get; set; }
       /// <summary>
       /// QQ加密密碼
       /// </summary>
       public string P { get; set; }
       /// <summary>
       /// QQ微博的Cookie容器
       /// </summary>
       public CookieContainer WeiboCookieContainer { get; set; }
       /// <summary>
       /// QQ微博的Cookie字符
       /// </summary>
       public string WeiboCookieString { get; set; }
       /// <summary>
       /// QQ微博對應的Sid
       /// </summary>
       public string Sid { get; set; }
       /// <summary>
       /// 目前帳號的狀態
       /// </summary>
       public Status CurrentStatus { get; set; }
       /// <summary>
       /// 帳號類型
       /// </summary>
       public AccountStyle AccountStyle { get; set; }
       /// <summary>
       /// 是否需要驗證碼
       /// </summary>
       public bool NeedVerify { get; set; }
       /// <summary>
       /// 驗證碼圖片
       /// </summary>
       public Image VerifyImage { get; set; }
       /// <summary>
       /// 驗證碼字符串
       /// </summary>
       public string VerifyCode { get; set; }
       
       #endregion
       #region 構造函數
       public Account()
       {
           Init();
       }
       public Account(string uin, string password)
       {
           this.Uin = uin;
           this.Password = password;
           Init();
       }
       #endregion
       #region 私有函數
       private void Init()
       {
           this.WeiboCookieContainer = new CookieContainer();
           this.CurrentStatus = Status.Unlogin;
           this.AccountStyle = AccountStyle.Unknow;
       }
       #endregion
}
}

上面的那些都不是關鍵,我們要做的第一步還是完成“判斷驗證碼>輸入驗證碼(如果有的話)>登錄”,除了要我完成Http模擬請求之外還要從返回的結果中提取有用的信息。

 #region 登錄過程
       /// <summary>
       /// 判斷登錄微博是否需要驗證碼
       /// </summary>
       /// <returns></returns>
       public bool CheckVerify_Weibo(ref string vctype)
       {
           string url = "", html;
           url = string.Format("http://check.ptlogin2.qq.com/check?uin={0}@qq.com&appid=46000101&ptlang=2052&r={1}", this.Uin,new Random().NextDouble());
           html = HttpHelper.GetHtml(url, this.WeiboCookieContainer);
           if (string.IsNullOrEmpty(html)) return false;
           string pattern = @"ptui_checkVC\('(?'need'[^']*)','(?'vctype'[^']*)','[^']*'\);";
           string need = html.Match(pattern, "need");
           vctype = html.Match(pattern, "vctype");
           if (need == "1")
           {
               this.CurrentStatus = Status.NeedVerify;
              this.VerifyImage= this.GetImage();
               return true;
           }
           else
           {
               this.CurrentStatus = Status.Unlogin;
               this.VerifyCode = vctype;
               return false;
           }
         
       }
       /// <summary>
       /// 獲取顯示驗證碼
       /// </summary>
       /// <returns></returns>
       public Image GetImage()
       {
         string url = string.Format("http://captcha.qq.com/getimage?aid=46000101&r=0.38706237439032276&uin={0}@qq.com", this.Uin);
           Stream stream = HttpHelper.GetStream(url, this.WeiboCookieContainer);
           Image image = Image.FromStream(stream);
           return image;
       }
       /// <summary>
       /// 登錄
       /// </summary>
       /// <returns></returns>
       public string Login()
       {
           string uin,password,verifyCode;
           uin = this.Uin;
           password = this.Password;
           verifyCode = this.VerifyCode;
           string html="";
        if (string.IsNullOrEmpty(uin) || string.IsNullOrEmpty(password))
               throw new Exception("沒有添加帳號,或帳號的密碼為空");
           if (string.IsNullOrEmpty(verifyCode))
               throw new Exception("驗證碼為空,無法繼續登錄");
           this.P = QQMd5.Encrypt(uin,password,verifyCode);
           string url = string.Format("http://ptlogin2.qq.com/login?ptlang=2052&u={0}@qq.com&p={1}&verifycode={2}&low_login_enable=1&low_login_hour=720&css=http://imgcache.qq.com/ptcss/b4/wb/46000101/login1.css&aid=46000101&mibao_css=m_weibo&u1=http%3A%2F%2Ft.qq.com&ptredirect=1&h=1&from_ui=1&dumy=&fp=loginerroralert&action=7-9-1381063&g=1&t=1&dummy=",
                                     uin, this.P, verifyCode);
           html = HttpHelper.GetHtml(url, this.WeiboCookieContainer);
           if (html.Contains("您輸入的驗證碼不正確,請重新輸入"))
               throw new Exception(string.Format("驗證碼輸入不正確"));
           else if (html.Contains("您輸入的帳號或密碼不正確,請重新輸入"))
               throw new Exception(string.Format("帳號或密碼不正確"));
           else if (html.Contains("登錄成功"))
           {
               html = string.Format("登錄成功");
               this.CurrentStatus = Status.Login;
             
           }
         
           return html;
         }

由於本人不太喜歡用已經做好的輪子去用Json處理類(比如Newtonsoft.net),所以一般處理都是用的正則表達式,各位也可以自己用JsonObejct類去處理,不用跟我一樣用正則這種笨方法。
3.獲取必要信息[提取微博數據]

 public string GetInfo()
       {string html="";
           try
           {
               string url = "http://t.qq.com";
               html = HttpHelper.GetHtml(url, this.WeiboCookieContainer);
               string pattern = @"href=""(?'mypage'[^""]*)""><u>首頁";
               string mypage = html.Match(pattern, "mypage");
               this.MyPage = mypage;
               if (string.IsNullOrEmpty(mypage)) throw new Exception("獲取微博話題列表失敗");
               pattern = @"boss=""btnWideSideMyNick"">(?'nick'[^<]*)</a>";
               string nick = html.Match(pattern, "nick");
               if (html.Contains("立即開通")) this.CurrentStatus = Status.NotRegist;
               this.Nick = nick;
               html = "成功獲取微博話題列表";
           }
           catch(Exception e)
           {
               html = e.Message;
           }
           return html;
       }
       public List<FriendInfo> GetQQFriendList()
       {
           string account = ""; string r = "1351620387406";
           account = this.MyPage.ToLower().Replace("http://t.qq.com/", "");
           string url = string.Format("http://api.t.qq.com/share/qqList.php?account={0}&r={1}&apiType=8&apiHost=http://api.t.qq.com&_r={1}",
                                                account,r);
           HttpHelper.Referer = this.MyPage;
           HttpHelper.ExtendHeadData = string.Format("rf:{0}", this.MyPage);
           string html = HttpHelper.GetHtml(url, this.WeiboCookieContainer);
          
           HttpHelper.Referer = "";
           HttpHelper.ExtendHeadData = "";
           Regex regex = new Regex(@"(""sortId"":(?'sordId'[^""]+),)*""name"":""(?'name'[^""]+)"",(""groupId"":(?'groupId'[^,]+),)*(""member"":(?'member'\[[^\]]*\]))*", RegexOptions.IgnoreCase);
           MatchCollection matches = regex.Matches(html);
           List<FriendInfo> list = new List<FriendInfo>();
           for (int i = 0; i < matches.Count; i++)
           {
               
               string sortId = matches[i].Groups["sortId"].Value;
               string name = matches[i].Groups["name"].Value;
               string groupId = matches[i].Groups["groupId"].Value;
               string member = matches[i].Groups["member"].Value;
               Regex memberRegex = new Regex(@"""qq"":""(?'qq'[^""]*)"",""pic"":null,""nick"":""(?'nick'[^""]*)""", RegexOptions.IgnoreCase);
               MatchCollection memberMatches = memberRegex.Matches(member);
               for (int j = 0; j < memberMatches.Count; j++)
               {
                   string qq = memberMatches[j].Groups["qq"].Value;
                   string nick = memberMatches[j].Groups["nick"].Value;
                   FriendInfo friendInfo = new FriendInfo();
                   friendInfo.Uin = qq;
                  friendInfo.Name = WebQQ.Converter.Unicode_js_1(name);
                 
                   friendInfo.Nick = WebQQ.Converter.Unicode_js_1(nick);
                   if (friendInfo.Name == "最近聯系人") continue;
                   friendInfo.SortId = sortId;
                   friendInfo.GroupId = groupId;
                   friendInfo.QQ = Uin;
                    list.Add(friendInfo);

               }


           }
           return list;
       }

上面這一步不一定是必須的,但是沒有這一步,我們后面所要實現的功能就會很困難。包括發送分享給QQ,這一步,因為要發送的QQ好友的號碼不是真正的號碼,而是一個系統隨機生成的好友序列號的MD5加密字段。因此,我們也無法用於分享QQ給陌生人號碼。

4.分享

 #region 分享
       public string MailShare(string shareId,string toList,string subject,string reason)
       {
           string url, html;
           url = "http://api.t.qq.com/mail/mailShare.php";
           HttpHelper.ExtendHeadData =string.Format("rf:{0}",this.MyPage);
           HttpHelper.Referer = "http://api.t.qq.com/proxy.html";
           string mail = HttpUtility.UrlEncode(Encoding.UTF8.GetBytes(this.Mail));
           string maillist = HttpUtility.UrlEncode(Encoding.UTF8.GetBytes(toList));
            subject = HttpUtility.UrlEncode(Encoding.UTF8.GetBytes(subject));
            reason = HttpUtility.UrlEncode(Encoding.UTF8.GetBytes(reason));
           string postString = string.Format("mailAddr={0}&mlist={1}&subject={2}&body={3}&reason={4}&apiType=8&apiHost=http://api.t.qq.com",
                                           mail,toList,subject,shareId,reason);
           html = HttpHelper.GetHtml(url, postString, this.WeiboCookieContainer);
           HttpHelper.Referer = "";

           return html;
       }
       public string ShareQZone(string shareId, string reason)
       {
           string url = "http://api.t.qq.com/share/shareQzone.php";
           HttpHelper.ExtendHeadData = string.Format("rf:{0}", this.MyPage);
           HttpHelper.Referer = "http://api.t.qq.com/proxy.html";
           reason = HttpUtility.UrlEncode(Encoding.UTF8.GetBytes(reason));
           string postString = string.Format("id={0}&reason={1}&apiType=8&apiHost=http://api.t.qq.com",shareId,reason);
          string html = HttpHelper.GetHtml(url, postString, this.WeiboCookieContainer);
           HttpHelper.Referer = "";
           return html;
       }
       public string ShareMsg(string shareId,string uins,string group)
       {
           string url = "http://api.t.qq.com/share/shareMsg.php";
           string postString = string.Format("id={0}&uins={1}&group={2}&apiType=8&apiHost=http://api.t.qq.com",
                                   shareId,uins,group);
           HttpHelper.ExtendHeadData = string.Format("rf:{0}", this.MyPage);
           HttpHelper.Referer = "http://api.t.qq.com/proxy.html";
           string html = HttpHelper.GetHtml(url, postString, this.WeiboCookieContainer);
           HttpHelper.Referer = "";
           return html;
       }
       public string Pm_Mgr(string content,string target)
       {
           string url = "http://api.t.qq.com/inbox/pm_mgr.php";
           content = HttpUtility.UrlEncode(Encoding.UTF8.GetBytes(content));
           target = HttpUtility.UrlEncode(Encoding.UTF8.GetBytes(target));
           string postString = string.Format("source=&ptid=&roomid=&content={0}&fid=&arturl=&murl=&target={1}&func=send&ef=js&pmlang=zh_CN&apiType=8&apiHost=http://api.t.qq.com",
                                  content,target);//wuwenjun20102008,niefeng101
           string html = HttpHelper.GetHtml(url,postString, this.WeiboCookieContainer);
           return html;
       }
      #endregion

當然,給大家分享上面的分析結果不是讓大家去干一些讓人討厭的事(大家都懂的),僅僅是為那些愛好Http協議模擬的提供參考的方便。如果有和我一樣對這方面有共同愛好,請繼續關注本人的博客
教程每天都更新,歡迎繼續關注!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM