新浪微博开放平台开发步骤简介(适合新手看)
我也是个新手,也是第一次使用开放平台做开发,刚开始感到无处下手,经过半天的摸索终于成功的调用了API,现在把这点经验介绍给新手(高手就没必要看了,当然,如果你能提些意见和建议,我感激不尽),愿同大家一起交流。
本例介绍的是如何用API提交数据(发布一条微博)和用API获取数据(获取最新更新的20条公共微博消息),也就是官方API中的“获取下行数据集(timeline)接口”下的“statuses/public_timeline 获取最新更新的公共微博消息”和“微博访问接口”下的“statuses/update 发布一条微博信息”。
首先你要有一个新浪微博帐号,还要申请一个app key(具体请参考http://open.t.sina.com.cn/wiki/index.php/%E6%96%B0%E6%89%8B%E6%8C%87%E5%8D%97),然后在VS中新建一个解决方案,在解决方案中添加一个类库和一个网站,并添加引用(网站引用类库)。
由于发布微博是POST请求,获取数据是GET请求,且通过HTTP普通验证(Basic Authentication)方式授权,因此我把这些功能写在一个类中(放在类库中),代码如下(这个类参考了http://www.cnblogs.com/cmt/archive/2010/05/13/1733904.html,没有仔细考虑是否达到了通用):
using System.Net;
using System.IO;
namespace SinaMiniBlogLib
{
public class SendRequest
{
string username;
string password;
string key;
public string UsernamePassword
{
get { return username + ":" + password; }
}
#region 构造函数
public SendRequest()
{
username = "你的新浪微博帐号";
password = "你的新浪微博密码";
key = "你申请的app key";
}
public SendRequest(string username, string password,string key)
{
this.username = username;
this.password = password;
this.key = key;
}
#endregion
#region 发送GET请求
/// <summary>
/// 发送GET请求
/// </summary>
/// <param name="url">地址</param>
/// <returns>string</returns>
public string SendGetRequest(string url)
{
string Content=string.Empty;
//准备用于发起请求的HttpWebRequest对象:
WebRequest webRequest = WebRequest.Create(url+"?source="+key);
HttpWebRequest httpRequest = webRequest as HttpWebRequest;
//准备用于用户验证的凭据
CredentialCache myCache = new CredentialCache();
myCache.Add(new Uri(url), "Basic", new NetworkCredential(username, password));
httpRequest.Credentials = myCache;
httpRequest.Headers.Add("Authorization", "Basic " + Convert.ToBase64String(new System.Text.ASCIIEncoding().GetBytes(UsernamePassword)));
//GET方法
httpRequest.Method = "GET";
HttpWebResponse httpRespone = (HttpWebResponse)httpRequest.GetResponse();
if (httpRespone != null && httpRespone.StatusCode == HttpStatusCode.OK)
{
using (StreamReader sr = new StreamReader(httpRespone.GetResponseStream()))
{
Content = sr.ReadToEnd();
}
}
return Content;
}
#endregion
#region 发送POST请求
/// <summary>
/// 发送POST请求
/// </summary>
/// <param name="url">网址</param>
/// <param name="Content">内容</param>
/// <returns>string</returns>
public string SendPostRequest(string url,string Content)
{
string result = string.Empty;
//准备调用的URL及需要POST的数据:
string data = "source="+key+"&status=" + Content;
//准备用于发起请求的HttpWebRequest对象:
WebRequest webRequest = WebRequest.Create(url);
HttpWebRequest httpRequest = webRequest as HttpWebRequest;
//准备用于用户验证的凭据
CredentialCache myCache = new CredentialCache();
myCache.Add(new Uri(url), "Basic", new NetworkCredential(username, password));
httpRequest.Credentials = myCache;
httpRequest.Headers.Add("Authorization", "Basic " + Convert.ToBase64String(new System.Text.ASCIIEncoding().GetBytes(UsernamePassword)));
//发起POST请求
httpRequest.Method = "POST";
httpRequest.ContentType = "application/x-www-form-urlencoded";
System.Text.Encoding encoding = System.Text.Encoding.ASCII;
byte[] bytesToPost = encoding.GetBytes(data);
httpRequest.ContentLength = bytesToPost.Length;
System.IO.Stream requestStream = httpRequest.GetRequestStream();
requestStream.Write(bytesToPost, 0, bytesToPost.Length);
requestStream.Close();
//获取服务端的响应内容
System.Net.WebResponse wr = httpRequest.GetResponse();
System.IO.Stream receiveStream = wr.GetResponseStream();
using (System.IO.StreamReader reader = new System.IO.StreamReader(receiveStream, System.Text.Encoding.UTF8))
{
result = reader.ReadToEnd();
}
return result;
}
#endregion
}
}
然后在类库中新建两个实体类status和user,字段与官方API中一致:
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SinaMiniBlogLib
{
public class status
{
public status()
{
user = new user();
}
#region 属性
private DateTime created_at;
private string id;
private string text;
private string source;
private bool favorited;
private bool truncated;
private string in_reply_to_status_id;
private string in_reply_to_user_id;
private string in_reply_to_screen_name;
private string thumbnail_pic;
private string bmiddle_pic;
private string original_pic;
private user user;
private status retweeted_status;
#endregion
#region 属性封装
/// <summary>
/// 创建时间
/// </summary>
public DateTime Created_at
{
get { return created_at; }
set { created_at = value; }
}
/// <summary>
/// 微博ID
/// </summary>
public string Id
{
get { return id; }
set { id = value; }
}
/// <summary>
/// 微博信息内容
/// </summary>
public string Text
{
get { return text; }
set { text = value; }
}
/// <summary>
/// 微博来源
/// </summary>
public string Source
{
get { return source; }
set { source = value; }
}
/// <summary>
/// 是否已收藏
/// </summary>
public bool Favorited
{
get { return favorited; }
set { favorited = value; }
}
/// <summary>
/// 是否被截断
/// </summary>
public bool Truncated
{
get { return truncated; }
set { truncated = value; }
}
/// <summary>
/// 回复ID
/// </summary>
public string In_reply_to_status_id
{
get { return in_reply_to_status_id; }
set { in_reply_to_status_id = value; }
}
/// <summary>
/// 回复人UID
/// </summary>
public string In_reply_to_user_id
{
get { return in_reply_to_user_id; }
set { in_reply_to_user_id = value; }
}
/// <summary>
/// 回复人昵称
/// </summary>
public string In_reply_to_screen_name
{
get { return in_reply_to_screen_name; }
set { in_reply_to_screen_name = value; }
}
/// <summary>
/// 缩略图
/// </summary>
public string Thumbnail_pic
{
get { return thumbnail_pic; }
set { thumbnail_pic = value; }
}
/// <summary>
/// 中型图片
/// </summary>
public string Bmiddle_pic
{
get { return bmiddle_pic; }
set { bmiddle_pic = value; }
}
/// <summary>
/// 原始图片
/// </summary>
public string Original_pic
{
get { return original_pic; }
set { original_pic = value; }
}
/// <summary>
/// 作者信息
/// </summary>
public user User
{
get { return user; }
set { user = value; }
}
/// <summary>
/// 转发的博文,内容为status,如果不是转发,则没有此字段
/// </summary>
public status Retweeted_status
{
get { return retweeted_status; }
set { retweeted_status = value; }
}
#endregion
}
}
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SinaMiniBlogLib
{
public class user
{
#region 属性
private string id;
private string screen_name;
private string name;
private int province;
private int city;
private string location;
private string description;
private string url;
private string profile_image_url;
private string domain;
private string gender;
private int followers_count;
private int friends_count;
private int statuses_count;
private int favourites_count;
private DateTime created_at;
private bool following;
private bool verified;
#endregion
#region 属性封装
/// <summary>
/// 用户UID
/// </summary>
public string Id
{
get { return id; }
set { id = value; }
}
/// <summary>
/// 微博昵称
/// </summary>
public string Screen_name
{
get { return screen_name; }
set { screen_name = value; }
}
/// <summary>
/// 友好显示名称,如Bill Gates(此特性暂不支持)
/// </summary>
public string Name
{
get { return name; }
set { name = value; }
}
/// <summary>
/// 省份编码(参考省份编码表)
/// </summary>
public int Province
{
get { return province; }
set { province = value; }
}
/// <summary>
/// 城市编码(参考城市编码表)
/// </summary>
public int City
{
get { return city; }
set { city = value; }
}
/// <summary>
/// 地址
/// </summary>
public string Location
{
get { return location; }
set { location = value; }
}
/// <summary>
/// 个人描述
/// </summary>
public string Description
{
get { return description; }
set { description = value; }
}
/// <summary>
/// 用户博客地址
/// </summary>
public string Url
{
get { return url; }
set { url = value; }
}
/// <summary>
/// 自定义图像
/// </summary>
public string Profile_image_url
{
get { return profile_image_url; }
set { profile_image_url = value; }
}
/// <summary>
/// 用户个性化URL
/// </summary>
public string Domain
{
get { return domain; }
set { domain = value; }
}
/// <summary>
/// 性别,m--男,f--女,n--未知
/// </summary>
public string Gender
{
get { return gender; }
set { gender = value; }
}
/// <summary>
/// 粉丝数
/// </summary>
public int Followers_count
{
get { return followers_count; }
set { followers_count = value; }
}
/// <summary>
/// 关注数
/// </summary>
public int Friends_count
{
get { return friends_count; }
set { friends_count = value; }
}
/// <summary>
/// 微博数
/// </summary>
public int Statuses_count
{
get { return statuses_count; }
set { statuses_count = value; }
}
/// <summary>
/// 收藏数
/// </summary>
public int Favourites_count
{
get { return favourites_count; }
set { favourites_count = value; }
}
/// <summary>
/// 创建时间
/// </summary>
public DateTime Created_at
{
get { return created_at; }
set { created_at = value; }
}
/// <summary>
/// 是否已关注(此特性暂不支持)
/// </summary>
public bool Following
{
get { return following; }
set { following = value; }
}
/// <summary>
/// 加V标示,是否微博认证用户
/// </summary>
public bool Verified
{
get { return verified; }
set { verified = value; }
}
#endregion
}
}
好了,经过上面的步骤,准备工作已经完毕,现在开始调用API,先看发布一条微博信息吧,虽然这篇文章(http://www.cnblogs.com/cmt/archive/2010/05/13/1733904.html)中介绍了,但为了本文的完整我还是贴上我的代码吧,在类库中添加一个微博访问类MiniBlogVisit类:
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SinaMiniBlogLib
{
public class MiniBlogVisit
{
/// <summary>
/// 发布一条微博
/// </summary>
/// <param name="url">地址</param>
/// <param name="Content">微博内容</param>
public void update(string url,string Content)
{
SendRequest send = new SendRequest();
send.SendPostRequest(url, Content);
}
}
}
调用其中的update方法就可以发布一条微博了哦。不过要注意的是这里的Content要用HttpUtility.UrlEncode进行编码,否则会出现乱码哦。
再看获取最新更新的20条公共微博消息,也就是官方API中的第一个接口,这里返回的是XML数据或JSON数据,大家可根据爱好自由选择,我选择的是返回XML数据。我的方法是把返回的XML数据写入一个XML文件中,再对XML文件进行解析,代码如下:
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
namespace SinaMiniBlogLib
{
public class GetNextLineData
{
#region public_timeline 获取最新更新的20条公共微博消息
/// <summary>
/// 获取最新更新的20条公共微博消息
/// </summary>
/// <param name="url">地址</param>
/// <param name="xmlpath">存放返回的微博信息的XML文件路径</param>
/// <returns>IList</returns>
public IList<status> public_timeline(string url,string xmlpath)
{
SendRequest send = new SendRequest();
//发送GET请求,得到XML格式的数据
string Content=send.SendGetRequest(url);
//如果XML文件不存在就创建
if (!System.IO.File.Exists(xmlpath))
{
System.IO.FileStream f = System.IO.File.Create(xmlpath);
f.Close();
}
//以覆盖的形式把数据写入XML文件
System.IO.StreamWriter f2 = new System.IO.StreamWriter(xmlpath, false, System.Text.Encoding.GetEncoding("UTF-8"));
f2.Write(Content);
f2.Close();
f2.Dispose();
status temp;
IList<status> statusList=new List<status>();
//解析XML文件
XmlDocument myXml = new XmlDocument();
myXml.Load(xmlpath);
XmlNode users = myXml.DocumentElement;
foreach (XmlNode node in users.ChildNodes)
{
if (node.Name == "status")
{
temp = new status();
foreach (XmlNode statusnode in node.ChildNodes)
{
switch (statusnode.Name)
{
case "created_at":
temp.Created_at =ConverDateTime(statusnode.InnerText);
break;
case "id":
temp.Id = statusnode.InnerText;
break;
case "text":
temp.Text = statusnode.InnerText;
break;
case "source":
temp.Source = statusnode.InnerXml;
break;
case "favorited":
temp.Favorited =bool.Parse(statusnode.InnerText);
break;
case "truncated":
temp.Truncated = bool.Parse(statusnode.InnerText);
break;
case "in_reply_to_status_id":
temp.In_reply_to_status_id = statusnode.InnerText;
break;
case "in_reply_to_user_id":
temp.In_reply_to_user_id = statusnode.InnerText;
break;
case "in_reply_to_screen_name":
temp.In_reply_to_screen_name = statusnode.InnerText;
break;
case "user":
XmlNode usernode = statusnode.ChildNodes[0];
switch (usernode.Name)
{
case "id":
temp.User.Id = usernode.InnerText;
break;
case "screen_name":
temp.User.Screen_name = usernode.InnerText;
break;
case "name":
temp.User.Name = usernode.InnerText;
break;
case "province":
temp.User.Province =Int32.Parse(usernode.InnerText);
break;
case "city":
temp.User.City =Int32.Parse(usernode.InnerText);
break;
case "location":
temp.User.Location = usernode.InnerText;
break;
case "description":
temp.User.Description = usernode.InnerText;
break;
case "url":
temp.User.Url = usernode.InnerText;
break;
case "profile_image_url":
temp.User.Profile_image_url = usernode.InnerText;
break;
case "domain":
temp.User.Domain = usernode.InnerText;
break;
case "gender":
temp.User.Gender = usernode.InnerText;
break;
case "followers_count":
temp.User.Followers_count =Int32.Parse( usernode.InnerText);
break;
case "friends_count":
temp.User.Friends_count = Int32.Parse(usernode.InnerText);
break;
case "statuses_count":
temp.User.Statuses_count = Int32.Parse(usernode.InnerText);
break;
case "favourites_count":
temp.User.Favourites_count = Int32.Parse(usernode.InnerText);
break;
case "created_at":
temp.User.Created_at =ConverDateTime(usernode.InnerText);
break;
case "following":
temp.User.Following = bool.Parse(usernode.InnerText);
break;
case "verified":
temp.User.Verified = bool.Parse(usernode.InnerText);
break;
}
break;
}
}
statusList.Add(temp);
}
}
return statusList;
}
#endregion
#region 日期转换
/// <summary>
/// 日期转换
/// </summary>
/// <param name="time">新浪微博中返回的类似"Mon Oct 18 12:28:54 +0800 2010"这样的时间</param>
/// <returns>DateTime</returns>
public DateTime ConverDateTime(string time)
{
string[] cx = time.Split(' ');
System.Globalization.DateTimeFormatInfo g = new System.Globalization.DateTimeFormatInfo();
g.LongDatePattern = "dd MMMM yyyy";
DateTime DT = DateTime.Parse(string.Format("{0} {1} {2} {3}", cx[2], cx[1], cx[5], cx[3]), g);
return DT;
}
#endregion
}
}
好了,现在就是调用了,调用做的比较简单,就是一个空的Default.aspx页面,后台代码如下:
using System.Web;
using SinaMiniBlogLib;
using System.Collections.Generic;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
try
{
//发布一条微博
MiniBlogVisit mini = new MiniBlogVisit();
//注意这里要用HttpUtility.UrlEncode进行编码,否则会出现乱码
mini.update("http://api.t.sina.com.cn/statuses/update.xml", HttpUtility.UrlEncode("测试一下XML!"));
//获取最新更新的20条公共微博消息
GetNextLineData linedata = new GetNextLineData();
IList<status> statusList = linedata.public_timeline("http://api.t.sina.com.cn/statuses/public_timeline.xml", Server.MapPath("NextLine.xml"));
//输出
foreach (status temp in statusList)
{
Response.Write(temp.Text+"<br/>"+temp.Created_at+" 来自"+temp.Source+"<br/><br/>");
}
}
catch (Exception ex)
{
ClientScript.RegisterStartupScript(this.GetType(), "sina", "<script type='text/javascript' language='javascript'>alert('出现异常,异常信息:" + ex.Message + "');</script>");
}
}
}
至此,全部代码已经写完,再看看完整的解决方案吧:
运行后效果如下:
第一次调用API,也是第一次写这么长的文章,欢迎大家多拍砖哈!!!