国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

新浪微博SDK開(kāi)發(fā)(1):總述

2019-11-14 16:36:22
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

花了幾天時(shí)間,消耗了九牛六虎之力,新浪微博大部分API已經(jīng)封裝,但有部分API實(shí)在太難封裝。

說(shuō)起這封裝,我必須嚴(yán)重地、從人品和技術(shù)層面鄙視一下新浪的程序員,實(shí)在太菜了。估計(jì)菜鳥(niǎo)都被大企業(yè)吸收了,菜到連面向?qū)ο蠖疾欢=ㄗh新浪的菜菜們向淘寶學(xué)習(xí)下,人家淘寶還同時(shí)有xml和JSON兩種數(shù)據(jù)格式。

同樣的內(nèi)容,返回的JSON對(duì)象居然會(huì)出現(xiàn)不同結(jié)構(gòu),更可惡的,像公共API中獲取城市列表,國(guó)家區(qū)域代碼列表的返回結(jié)果,實(shí)在讓人不得不發(fā)笑。那些JSON用JS讀起來(lái)都困難,更何況要進(jìn)行封裝呢。根本沒(méi)法封裝,因此在論壇上抱怨的人不少,可是新浪官方呢,置之不管,就當(dāng)沒(méi)看見(jiàn)一樣,看來(lái),大企業(yè)就是這點(diǎn)水平。

題外話(huà)不多說(shuō),回歸主題。除了權(quán)限不夠和無(wú)法封裝的API外,其余的API都封裝了。先上一張代碼地圖。

這圖有點(diǎn)像蜘蛛網(wǎng),非常有美感,可惜是靜止的,如果會(huì)動(dòng)的,一定很好看。

我不可能把代碼一行一行地向大家講述,因?yàn)檫@樣做會(huì)相當(dāng)惡心。現(xiàn)在菜菜們都整天拿開(kāi)源來(lái)裝逼,所以,為了迎合廣大菜菜所說(shuō)的所謂“趨勢(shì)”,我也決定把我這份亂七八糟的代碼向全人類(lèi)公開(kāi)。

下載地址:http://vdisk.weibo.com/s/z7iFc2gCCwC1b

 

接下來(lái),就給大家說(shuō)說(shuō)原理和思路,這才是編程的關(guān)鍵。

1、不管是微博API還是其他的開(kāi)放平臺(tái)的API,都有N多共同點(diǎn)。首先,用戶(hù)要用自己的帳號(hào)登錄,然后由用戶(hù)決定是否授權(quán)給我們的應(yīng)用程序,如果用戶(hù)已同意授權(quán),我們會(huì)得到一個(gè)授權(quán)碼(Code)。

2、拿到Code后,我們要用這個(gè)Code來(lái)?yè)Q取一個(gè)access Token,就相當(dāng)于用戶(hù)授予我們一把鑰匙,我們?cè)儆眠@把鑰匙去開(kāi)啟庫(kù)房的門(mén),然后取出一個(gè)臨時(shí)令牌,就好比在漢代,大臣代表天子巡視諸侯國(guó)時(shí),手里要持著天子的符節(jié)一樣。有了Token,我們的應(yīng)用才能進(jìn)行一系列操作。

 

微博的API的每一次調(diào)用,其實(shí)就是一輪HTTP請(qǐng)求-響應(yīng)的往返過(guò)程,說(shuō)白了,就是一問(wèn)一答,我們調(diào)用API是問(wèn),服務(wù)器完成相關(guān)處理后返回結(jié)果給我們,為答。我們也知道,HTTP發(fā)送數(shù)據(jù),用得最多的兩種方法是GET和POST,至于是GET還是POST,我們按照API文檔的說(shuō)明去干就行了。

 

而對(duì)于服務(wù)器返回的數(shù)據(jù)(JSON),我是通過(guò)數(shù)據(jù)協(xié)定的形式來(lái)進(jìn)行封裝的。比如:

一個(gè)表示用戶(hù)信息的回復(fù)JSON如下:

我們可以根據(jù)JSON中每個(gè)成員的名字,用代碼封裝成一個(gè)類(lèi)。

    /// <summary>    /// 用戶(hù)實(shí)體    /// </summary>    [DataContract]    public class UserInfo    {        /// <summary>        /// 用戶(hù)UID         /// </summary>        [DataMember(Name = "id")]        public long ID { get; set; }        /// <summary>        /// 字符串型的用戶(hù)UID        /// </summary>        [DataMember(Name = "idstr")]        public string IDStr { get; set; }        /// <summary>        /// 用戶(hù)昵稱(chēng)        /// </summary>        [DataMember(Name = "screen_name")]        public string ScreenName { get; set; }        /// <summary>        /// 友好顯示名稱(chēng)        /// </summary>        [DataMember(Name = "name")]        public string Name { get; set; }        /// <summary>        /// 用戶(hù)所在省級(jí)ID        /// </summary>        [DataMember(Name = "province")]        public int Province { get; set; }        /// <summary>        /// 用戶(hù)所在城市ID        /// </summary>        [DataMember(Name = "city")]        public int City { get; set; }        /// <summary>        /// 用戶(hù)所在地        /// </summary>        [DataMember(Name = "location")]        public string Location { get; set; }        /// <summary>        /// 用戶(hù)個(gè)人描述        /// </summary>        [DataMember(Name = "description")]        public string Description { get; set; }        /// <summary>        /// 用戶(hù)博客地址        /// </summary>        [DataMember(Name = "url")]        public string Url { get; set; }        /// <summary>        /// 用戶(hù)頭像地址(中圖),50×50像素        /// </summary>        [DataMember(Name = "profile_image_url")]        public string ProfileImageUrl { get; set; }        /// <summary>        /// 用戶(hù)的微博統(tǒng)一URL地址        /// </summary>        [DataMember(Name = "profile_url")]        public string ProfileUrl { get; set; }        /// <summary>        /// 用戶(hù)的個(gè)性化域名        /// </summary>        [DataMember(Name = "domain")]        public string Domain { get; set; }        /// <summary>        /// 用戶(hù)的微號(hào)        /// </summary>        [DataMember(Name = "weihao")]        public string WeiHao { get; set; }        /// <summary>        /// 性別,m:男、f:女、n:未知        /// </summary>        [DataMember(Name = "gender")]        public string Gender { get; set; }        /// <summary>        /// 粉絲數(shù)        /// </summary>        [DataMember(Name = "followers_count")]        public int FollowersCount { get; set; }        /// <summary>        /// 關(guān)注數(shù)        /// </summary>        [DataMember(Name = "friends_count")]        public int FriendsCount { get; set; }        /// <summary>        /// 微博數(shù)        /// </summary>        [DataMember(Name = "statuses_count")]        public int StatusesCount { get; set; }        /// <summary>        /// 收藏?cái)?shù)        /// </summary>        [DataMember(Name = "favourites_count")]        public int FavouritesCount { get; set; }        /// <summary>        /// 用戶(hù)創(chuàng)建(注冊(cè))時(shí)間        /// </summary>        [DataMember(Name = "created_at")]        public string CreatedAt { get; set; }        /// <summary>        /// 暫未支持        /// </summary>        [DataMember(Name = "following")]        public bool Following { get; set; }        /// <summary>        /// 是否允許所有人給我發(fā)私信,true:是,false:否        /// </summary>        [DataMember(Name = "allow_all_act_msg")]        public bool AllowAllActMsg { get; set; }        /// <summary>        /// 是否允許標(biāo)識(shí)用戶(hù)的地理位置,true:是,false:否        /// </summary>        [DataMember(Name = "geo_enabled")]        public bool GeoEnabled { get; set; }        /// <summary>        /// 是否是微博認(rèn)證用戶(hù),即加V用戶(hù),true:是,false:否        /// </summary>        [DataMember(Name = "verified")]        public bool Verified { get; set; }        /// <summary>        /// 暫未支持        /// </summary>        [DataMember(Name = "verified_type")]        public int VerifiedType { get; set; }        /// <summary>        /// 用戶(hù)備注信息        /// </summary>        [DataMember(Name = "remark")]        public string Remark { get; set; }        /// <summary>        /// 用戶(hù)的最近一條微博信息        /// </summary>        [DataMember(Name = "status")]        public Status Status { get; set; }        /// <summary>        /// 當(dāng)對(duì)象數(shù)據(jù)未返回完整微博信息時(shí),將填充該字段        /// </summary>        [DataMember(Name = "status_id")]        public long StatusID { get; set; }        /// <summary>        /// 是否允許所有人對(duì)我的微博進(jìn)行評(píng)論,true:是,false:否        /// </summary>        [DataMember(Name = "allow_all_comment")]        public bool AllowAllComment { get; set; }        /// <summary>        /// 用戶(hù)頭像地址(大圖),180×180像素        /// </summary>        [DataMember(Name = "avatar_large")]        public string AvatarLarge { get; set; }        /// <summary>        /// 用戶(hù)頭像地址(高清),高清頭像原圖        /// </summary>        [DataMember(Name = "avatar_hd")]        public string AvatarHd { get; set; }        /// <summary>        /// 認(rèn)證原因        /// </summary>        [DataMember(Name = "verified_reason")]        public string VerifiedReason { get; set; }        /// <summary>        /// 該用戶(hù)是否關(guān)注當(dāng)前登錄用戶(hù),true:是,false:否        /// </summary>        [DataMember(Name = "follow_me")]        public bool FollowMe { get; set; }        /// <summary>        /// 用戶(hù)的在線(xiàn)狀態(tài),0:不在線(xiàn)、1:在線(xiàn)        /// </summary>        [DataMember(Name = "online_status")]        public int OnlineStatus { get; set; }        /// <summary>        /// 用戶(hù)的互粉數(shù)        /// </summary>        [DataMember(Name = "bi_followers_count")]        public int BiFollowersCount { get; set; }        /// <summary>        /// 用戶(hù)當(dāng)前的語(yǔ)言版本,zh-cn:簡(jiǎn)體中文,zh-tw:繁體中文,en:英語(yǔ)        /// </summary>        [DataMember(Name = "lang")]        public string Lang { get; set; }    }

其中,Status屬性表示用戶(hù)發(fā)表的最新一條微博,它由一個(gè)表示微博的對(duì)象構(gòu)成。

同樣,我們也用一個(gè)數(shù)據(jù)協(xié)定類(lèi)來(lái)封裝它,表示一條微博的信息。

    /// <summary>    /// 微博實(shí)體    /// </summary>    [DataContract]    public class Status    {        /// <summary>        /// 微博創(chuàng)建時(shí)間        /// </summary>        [DataMember(Name = "created_at")]        public string CreateAt { get; set; }        /// <summary>        /// 微博ID        /// </summary>        [DataMember(Name = "id")]        public Int64 ID { get; set; }        /// <summary>        /// 微博MID         /// </summary>        [DataMember(Name = "mid")]        public Int64 MID { set; get; }        /// <summary>        /// 字符串型的微博ID        /// </summary>        [DataMember(Name = "idstr")]        public string IDStr { get; set; }        /// <summary>        /// 微博信息內(nèi)容        /// </summary>        [DataMember(Name = "text")]        public string Text { get; set; }        /// <summary>        /// 微博來(lái)源        /// </summary>        [DataMember(Name = "source")]        public string Source { get; set; }        /// <summary>        /// 是否已收藏,true:是,false:否        /// </summary>        [DataMember(Name = "favorited")]        public bool Favorited { get; set; }        /// <summary>        /// 是否被截?cái)啵瑃rue:是,false:否        /// </summary>        [DataMember(Name = "truncated")]        public bool Truncated { get; set; }        /// <summary>        /// (暫未支持)回復(fù)ID         /// </summary>        [DataMember(Name = "in_reply_to_status_id")]        public string InReplyToStatusID { get; set; }        /// <summary>        /// (暫未支持)回復(fù)人UID        /// </summary>        [DataMember(Name = "in_reply_to_user_id")]        public string InReplyToUserID { get; set; }        /// <summary>        /// (暫未支持)回復(fù)人昵稱(chēng)        /// </summary>        [DataMember(Name = "in_reply_to_screen_name")]        public string InReplyToScreenName { get; set; }        /// <summary>        /// 縮略圖片地址        /// </summary>        [DataMember(Name = "thumbnail_pic")]        public string ThumbnailPic { get; set; }        /// <summary>        /// 中等尺寸圖片地址        /// </summary>        [DataMember(Name = "bmiddle_pic")]        public string BmiddlePic { get; set; }        /// <summary>        /// 原始圖片地址        /// </summary>        [DataMember(Name = "original_pic")]        public string OriginalPic { get; set; }        /// <summary>        /// 地理信息        /// </summary>        [DataMember(Name = "geo")]        public GeoInfo Geo { get; set; }        /// <summary>        /// 微博作者的用戶(hù)信息        /// </summary>        [DataMember(Name = "user")]        public UserInfo User { get; set; }        /// <summary>        /// 被轉(zhuǎn)發(fā)的原微博信息字段,當(dāng)該微博為轉(zhuǎn)發(fā)微博時(shí)返回        /// </summary>        [DataMember(Name = "retweeted_status")]        public Status RetweetedStatus { get; set; }        /// <summary>        /// 轉(zhuǎn)發(fā)數(shù)        /// </summary>        [DataMember(Name = "reposts_count")]        public int RepostsCount { get; set; }        /// <summary>        /// 評(píng)論數(shù)        /// </summary>        [DataMember(Name = "comments_count")]        public int CommentsCount { get; set; }        /// <summary>        /// 表態(tài)數(shù)        /// </summary>        [DataMember(Name = "attitudes_count")]        public int AttitudesCount { get; set; }        /// <summary>        /// 暫未支持        /// </summary>        [DataMember(Name = "mlevel")]        public int Mlevel { get; set; }        /// <summary>        /// 微博的可見(jiàn)性及指定可見(jiàn)分組信息。該object中type取值,0:普通微博,1:私密微博,3:指定分組微博,4:密友微博;list_id為分組的組號(hào)        /// </summary>        [DataMember(Name = "visible")]        public dynamic Visible { get; set; }        /// <summary>        /// 微博配圖地址。多圖時(shí)返回多圖鏈接。無(wú)配圖返回“[]”         /// </summary>        [DataMember(Name = "pic_urls")]        public dynamic PicUrls { get; set; }        /// <summary>        /// 微博流內(nèi)的推廣微博ID         /// </summary>        [DataMember(Name = "ad")]        public dynamic Ad { get; set; }        /// <summary>        /// 當(dāng)不返回user字段時(shí),此屬性可填充UID        /// </summary>        [DataMember(Name = "uid")]        public long Uid { get; set; }    }

我們?cè)诮邮盏椒?wù)器的回應(yīng)后,直接對(duì)數(shù)據(jù)進(jìn)行反序列化,就可以得到這些數(shù)據(jù)的封裝實(shí)例,面向?qū)ο螅僮髌饋?lái)更方便。這些被封裝的基本類(lèi)型,我都放到了Models目錄下。為了實(shí)現(xiàn)反序列化,我定義了一個(gè)類(lèi),公開(kāi)一個(gè)靜態(tài)方法,以便從JSON數(shù)據(jù)生成對(duì)象實(shí)例。

因?yàn)槲覀円葱蛄谢念?lèi)型是多種多樣的,無(wú)法定論,因此,這里使用泛型參數(shù)較合適。具體反序列化為哪種類(lèi)型的實(shí)例,在運(yùn)行時(shí)決定。

由于每個(gè)API的調(diào)用都是一輪HTTP請(qǐng)求/回應(yīng),無(wú)論你調(diào)用哪個(gè)API都一樣,這個(gè)行為是通過(guò)的,所以,我就統(tǒng)一進(jìn)行提取,并使用.NET 4.5新增的HttpClient類(lèi)來(lái)處理,這個(gè)類(lèi)很強(qiáng)大,把一些不太好處理的HTTP請(qǐng)求都為我們封裝好了,尤其是像form-data這種POST的數(shù)據(jù),如MultiPart form data這些,尤其是向服務(wù)器上傳文件時(shí)較容易處理,省去許多不必要的機(jī)械性工作,將人類(lèi)從無(wú)必要的代碼中解放出來(lái),極大地提高生產(chǎn)率,這是.NET最牛X的地方。

        internal static async Task<TResult> SendRequestWithMultipartFormDataAsync<TResult>(string relateUrl, IDictionary<string, object> parms, string filename)        {            Uri reqUri = new Uri(API_BASE_RUI);            reqUri = new Uri(reqUri, relateUrl);            TResult result = default(TResult);            using (HttpClient client = new HttpClient())            {                string b = "---------------------" + DateTime.Now.Ticks.ToString("x");                MultipartFormDataContent formData = new MultipartFormDataContent(b);                foreach (var pair in parms)                {                    string str = pair.Value as string;                    if (str != null)                    {                        StringContent stringContent = new StringContent(pair.Value as string);                        formData.Add(stringContent, pair.Key);                    }                    Stream stream = pair.Value as Stream;                    if (stream != null)                    {                        StreamContent streamContent = new StreamContent(stream);                        formData.Add(streamContent, pair.Key, filename);                    }                }                var response = await client.PostAsync(reqUri, formData);                if (response.IsSuccessStatusCode)                {                    using (Stream backstream = await response.Content.ReadAsStreamAsync())                    {                        result = JsonSerializeHelper.ReadDataFromJson<TResult>(backstream);                    }                }                else                {                    ErrorData err = null;                    using (Stream errstream = await response.Content.ReadAsStreamAsync())                    {                        err = JsonSerializeHelper.ReadDataFromJson<ErrorData>(errstream);                    }                    throw new WeiboException(err);                }            }            return result;        }        internal static async Task<string> HttpGetStringAsync(string relateUrl)        {            Uri base_uri = new Uri(API_BASE_RUI);            Uri request_uri = new Uri(base_uri, relateUrl);            string result = "";            using (HttpClient client = new HttpClient())            {                result = await client.GetStringAsync(request_uri);            }            return result;        }        internal static async Task<Stream> HttpGetStreamAsync(string relateUrl)        {            Uri base_uri = new Uri(API_BASE_RUI);            base_uri = new Uri(base_uri, relateUrl);            Stream streamres = null;            using (HttpClient client = new HttpClient())            {                var streamtmp = await client.GetStreamAsync(base_uri);                streamres = new MemoryStream();                streamtmp.CopyTo(streamres);                streamtmp.Dispose();            }            return streamres;        }

上面僅僅列舉了一兩個(gè)方法,詳細(xì)的代碼大家可以下載源代碼看。

在我發(fā)布的解決方案中,有一個(gè)項(xiàng)目名為WeiboTest,它是一個(gè)單元測(cè)試項(xiàng)目,是我在封裝API過(guò)程用來(lái)測(cè)試調(diào)用而寫(xiě)的。

這個(gè)SDK可用在桌面程序和Web應(yīng)用程序中,對(duì)于WP和Store App,我一開(kāi)始是考慮建一個(gè)可移植的Portable項(xiàng)目的,但由于我僅在試水階段,后來(lái)就沒(méi)考慮移植了,其實(shí)絕大部分代碼是可以通用的,但有一小部分不行,比如文件操作就不能通用,因?yàn)閃P上的文件是通過(guò)獨(dú)立存儲(chǔ)來(lái)處理的,而不像桌面環(huán)境中那樣使用物理文件來(lái)處理。等代碼完善后,我會(huì)考慮將它改為一個(gè)通用類(lèi)庫(kù)。

 

下面就介紹一下我封裝了哪些API。

一、登錄授權(quán)部分我合為一體了,

不使用新浪彈出的授權(quán)頁(yè)面,而是直接模擬用戶(hù)登錄時(shí)POST的數(shù)據(jù),直接獲取Code,然后調(diào)用OAuth2的API換取Token。同時(shí)還公開(kāi)用于取消授權(quán)的RevokeOAuth2Async。

二、微博模塊。

  1、獲取最近的公共微博列表,

  2、獲取好友/關(guān)注人/自己的最新微博列表。

  3、獲取與當(dāng)前登錄用戶(hù)相互關(guān)注的用戶(hù)的最新微博列表。

  4、獲取某條微博的轉(zhuǎn)發(fā)列表。

  5、獲取@當(dāng)前用戶(hù) 的微博列表。

  6、根據(jù)微博ID獲取單條微博的詳細(xì)信息。

  7、批量獲取微博的轉(zhuǎn)發(fā)數(shù)和評(píng)論數(shù)。

  8、微博ID和MID的相互獲取。

  9、獲取微博官方表情列表。

  10、轉(zhuǎn)發(fā)微博。

  11、發(fā)表微博 / 發(fā)表帶圖片的微博。

  12、刪除微博。

三、評(píng)論模塊。

  1、獲取某條微博的評(píng)論列表。

  2、獲取當(dāng)前登錄用戶(hù)所發(fā)表的評(píng)論列表。

  3、獲取當(dāng)前用戶(hù)接收到的評(píng)論列表。

  4、獲取@當(dāng)前用戶(hù)的評(píng)論列表。

  5、批量獲取評(píng)論列表。

  6、發(fā)表評(píng)論。

  7、刪除指定評(píng)論。

  8、批量刪除評(píng)論。

  9、回復(fù)某條評(píng)論。

四、帳號(hào)模塊。

  1、獲取當(dāng)前用戶(hù)的隱私設(shè)置信息。是設(shè)置項(xiàng),不是獲取隱私,別想歪了。

  2、獲取學(xué)校列表,這個(gè)好像沒(méi)什么用。

五、關(guān)系模塊。

  1、獲取當(dāng)前登錄用戶(hù)的關(guān)注列表。

  2、獲取兩個(gè)用戶(hù)之間的共同關(guān)注人列表。比如我關(guān)注了A,而C也關(guān)注了A,因而我和C的共同關(guān)注人就是A。

  3、獲取用戶(hù)的相互關(guān)注人列表。也就是有哪些人跟我互粉。

  4、獲取當(dāng)前用戶(hù)的粉絲列表。即哪些人關(guān)注了我。

  5、獲取用戶(hù)的活躍粉絲列表。這個(gè)不知道干什么的,反正我測(cè)試的時(shí)候返回空。

  6、獲取當(dāng)前登錄用戶(hù)關(guān)注列表中同時(shí)關(guān)注了某用戶(hù)的列表。比如,我關(guān)注了A,獲取我關(guān)注的用戶(hù)中也關(guān)注了A的用戶(hù)列表。

  7、關(guān)注一位用戶(hù)。

  8、取消關(guān)注某位用戶(hù)。

六、用戶(hù)模塊。

  1、根據(jù)用戶(hù)ID獲取用戶(hù)信息。

  2、批量獲取用戶(hù)的關(guān)注數(shù)、粉絲數(shù)、微博數(shù)。

  3、通過(guò)個(gè)性域名獲取用戶(hù)信息以及最新發(fā)表的一條微博。

七、短鏈接模塊。

  1、長(zhǎng)鏈接轉(zhuǎn)為短鏈接。

  2、短鏈接轉(zhuǎn)為長(zhǎng)鏈接。

八、地理位置模塊。

  1、根據(jù)IP地址返回地理信息。

  2、根據(jù)具體地址返回地理坐標(biāo)信息。

  3、根據(jù)地理坐標(biāo)(經(jīng)度,緯度)返回地址信息。

 

這個(gè)SDK不算很完美,由于新浪的程序員比較菜,有些JSON數(shù)據(jù)結(jié)構(gòu)相當(dāng)不合理,暫時(shí)無(wú)法封裝,等到哪天我想到解決方法后再補(bǔ)充。


發(fā)表評(píng)論 共有條評(píng)論
用戶(hù)名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 龙胜| 沅江市| 萝北县| 德惠市| 永平县| 镇坪县| 会泽县| 招远市| 丹凤县| 吴桥县| 江都市| 沙洋县| 石家庄市| 岳阳县| 富蕴县| 怀安县| 晋中市| 咸宁市| 安阳县| 同德县| 余干县| 昌邑市| 四川省| 隆化县| 烟台市| 高要市| 佛学| 丹棱县| 开封市| 会同县| 景东| 逊克县| 博罗县| 龙门县| 湖南省| 扶绥县| 平定县| 鹤峰县| 酒泉市| 洪泽县| 平顶山市|