博客的分类比较混乱,那是随笔又比较多,一个个去修改很麻烦,所以参考网上写了个程序,用以批量修改博客。
代码还有以下问题,当获取单个Post,因服务器返回的postid被影射为int64类型,而实际接口应该是string类型。因此会报转换错误,目前还没有想到好的解决方法。
首先需要引用CookComputing.XmlRpc,项目属性---应用程序---目标框架选.Net Framework 4 而非 Client Profile
代码如下:
1. 新建windows窗体程序。
2. 新建Structs.cs文件,代码如下:
1 using System; 2 using CookComputing.XmlRpc; 3 4 namespace WindowsFormsApplication1 5 { 6 7 #region 微软MSN网站 使用的 MetaWeblog API. 8 /// 这个结构代表用户的博客基本信息 9 /// </summary> 10 [XmlRpcMissingMapping(MappingAction.Ignore)] 11 public struct UserBlog 12 { 13 public string url; 14 public string blogid; 15 public string blogName; 16 } 17 18 19 /// <summary> 20 /// 这个结构代表用户信息 21 /// </summary> 22 [XmlRpcMissingMapping(MappingAction.Ignore)] 23 public struct UserInfo 24 { 25 public string url; 26 public string blogid; 27 public string blogName; 28 public string firstname; 29 public string lastname; 30 public string email; 31 public string nickname; 32 } 33 34 35 /// <summary> 36 /// 这个结构代表博客分类信息 37 /// 这后面的getCategories()方法会取到CATEGORY数据。 38 /// </summary> 39 [XmlRpcMissingMapping(MappingAction.Ignore)] 40 public struct Category 41 { 42 public string description; 43 public string title; 44 public string htmlUrl; 45 public string rssUrl; 46 public string categoryid; 47 } 48 public struct WpCategory 49 { 50 public string name; 51 public string slug; 52 public int parent_id; 53 public string description; 54 } 55 /// <summary> 56 /// 这个结构代表博客( 文章 )信息。 57 /// 这后面的 editPost()方法, getRecentPosts()方法 和 getPost()方法 会取倒POST数据 . 58 /// </summary> 59 [XmlRpcMissingMapping(MappingAction.Ignore)] 60 public struct Post 61 { 62 public DateTime dateCreated; 63 public string description; 64 public string title; 65 public string postid; 66 public string[] categories; 67 // public Enclosure enclosure; 68 public string link; 69 public string permalink; 70 // public Source source; 71 public string userid; 72 public string mt_allow_comments; 73 public string mt_allow_pings; 74 public string mt_convert_breaks; 75 public string mt_text_more; 76 public string mt_excerpt; 77 public string mt_keywords; 78 public string wp_slug; 79 } 80 81 public struct Source 82 { 83 public string name; 84 public string url; 85 } 86 public struct Enclosure 87 { 88 public int length; 89 public string type; 90 public string url; 91 } 92 #endregion 93 94 95 #region 网站:http://msdn.microsoft.com/en-us/library/aa905670.aspx 96 ///// <summary> 97 ///// 微软MSN网站 使用的 MetaWeblog API. 98 //// 网站:http://msdn.microsoft.com/en-us/library/aa905670.aspx 99 ///// </summary> 100 public class M_MetaWeblog : XmlRpcClientProtocol 101 { 102 103 104 /// <summary> 105 /// Returns the most recent draft and non-draft blog posts sorted in descending order by publish date. 106 /// </summary> 107 /// <param name="blogid"> This should be the string MyBlog, which indicates that the post is being created in the user’s blog. </param> 108 /// <param name="username"> The name of the user’s space. </param> 109 /// <param name="password"> The user’s secret word. </param> 110 /// <param name="numberOfPosts"> The number of posts to return. The maximum value is 20. </param> 111 /// <returns></returns> 112 /// TODO:得到最近发布的帖子 113 [XmlRpcMethod("metaWeblog.getRecentPosts")] 114 public Post[] getRecentPosts( 115 string blogid, 116 string username, 117 string password, 118 int numberOfPosts) 119 { 120 return (Post[])this.Invoke("getRecentPosts", new object[] { blogid, username, password, numberOfPosts }); 121 } 122 123 124 [XmlRpcMethod("wp.newCategory")] 125 public object newCategory( 126 string blogid, 127 string username, 128 string password, 129 WpCategory category) 130 { 131 object tt = this.Invoke("newCategory", new object[] { blogid, username, password, category }); 132 return tt; 133 } 134 135 /// <summary> 136 /// Posts a new entry to a blog. 137 /// </summary> 138 /// <param name="blogid"> This should be the string MyBlog, which indicates that the post is being created in the user’s blog. </param> 139 /// <param name="username"> The name of the user’s space. </param> 140 /// <param name="password"> The user’s secret word. </param> 141 /// <param name="post"> A struct representing the content to update. </param> 142 /// <param name="publish"> If false, this is a draft post. </param> 143 /// <returns> The postid of the newly-created post. </returns> 144 /// TODO:增加一个最新的帖子 145 [XmlRpcMethod("metaWeblog.newPost")] 146 public string newPost( 147 string blogid, 148 string username, 149 string password, 150 Post content, 151 bool publish) 152 { 153 154 return (string)this.Invoke("newPost", new object[] { blogid, username, password, content, publish }); 155 } 156 157 /// <summary> 158 /// Edits an existing entry on a blog. 159 /// </summary> 160 /// <param name="postid"> The ID of the post to update. </param> 161 /// <param name="username"> The name of the user’s space. </param> 162 /// <param name="password"> The user’s secret word. </param> 163 /// <param name="post"> A struct representing the content to update. </param> 164 /// <param name="publish"> If false, this is a draft post. </param> 165 /// <returns> Always returns true. </returns> 166 /// TODO:更新一个帖子 167 [XmlRpcMethod("metaWeblog.editPost")] 168 public bool editPost( 169 string postid, 170 string username, 171 string password, 172 Post content, 173 bool publish) 174 { 175 176 return (bool)this.Invoke("editPost", new object[] { postid, username, password, content, publish }); 177 } 178 179 /// <summary> 180 /// Deletes a post from the blog. 181 /// </summary> 182 /// <param name="appKey"> This value is ignored. </param> 183 /// <param name="postid"> The ID of the post to update. </param> 184 /// <param name="username"> The name of the user’s space. </param> 185 /// <param name="password"> The user’s secret word. </param> 186 /// <param name="post"> A struct representing the content to update. </param> 187 /// <param name="publish"> This value is ignored. </param> 188 /// <returns> Always returns true. </returns> 189 /// TODO:删除一个帖子 190 [XmlRpcMethod("blogger.deletePost")] 191 public bool deletePost( 192 string appKey, 193 string postid, 194 string username, 195 string password, 196 bool publish) 197 { 198 199 return (bool)this.Invoke("deletePost", new object[] { appKey, postid, username, password, publish }); 200 } 201 202 203 /// <summary> 204 /// Returns information about the user’s space. An empty array is returned if the user does not have a space. 205 /// </summary> 206 /// <param name="appKey"> This value is ignored. </param> 207 /// <param name="postid"> The ID of the post to update. </param> 208 /// <param name="username"> The name of the user’s space. </param> 209 /// <param name="password"></param> 210 /// <returns> An array of structs that represents each of the user’s blogs. The array will contain a maximum of one struct, since a user can only have a single space with a single blog. </returns> 211 /// TODO:得到用户的博客清单 212 [XmlRpcMethod("blogger.getUsersBlogs")] 213 public UserBlog[] getUsersBlogs( 214 string appKey, 215 string username, 216 string password) 217 { 218 219 return (UserBlog[])this.Invoke("getUsersBlogs", new object[] { appKey, username, password }); 220 } 221 222 /// <summary> 223 /// Returns basic user info (name, e-mail, userid, and so on). 224 /// </summary> 225 /// <param name="appKey"> This value is ignored. </param> 226 /// <param name="postid"> The ID of the post to update. </param> 227 /// <param name="username"> The name of the user’s space. </param> 228 /// <param name="password"></param> 229 /// <returns> A struct containing profile information about the user. 230 /// Each struct will contain the following fields: nickname, userid, url, e-mail, 231 /// lastname, and firstname. </returns> 232 /// TODO:得到用户信息 233 [XmlRpcMethod("blogger.getUserInfo")] 234 public UserInfo getUserInfo( 235 string appKey, 236 string username, 237 string password) 238 { 239 240 return (UserInfo)this.Invoke("getUserInfo", new object[] { appKey, username, password }); 241 } 242 243 244 /// <summary> 245 /// Returns a specific entry from a blog. 246 /// </summary> 247 /// <param name="postid"> The ID of the post to update. </param> 248 /// <param name="username"> The name of the user’s space. </param> 249 /// <param name="password"> The user’s secret word. </param> 250 /// <returns> Always returns true. </returns> 251 /// TODO:获取一个帖子 252 [XmlRpcMethod("metaWeblog.getPost")] 253 public Post getPost( 254 string postid, 255 string username, 256 string password) 257 { 258 259 Post tt = (Post)this.Invoke("getPost", new object[] { postid, username, password }); 260 261 return tt; 262 } 263 264 public Post getPost(string temp) 265 { 266 return new Post(); 267 } 268 /// <summary> 269 /// Returns the list of categories that have been used in the blog. 270 /// </summary> 271 /// <param name="blogid"> This should be the string MyBlog, which indicates that the post is being created in the user’s blog. </param> 272 /// <param name="username"> The name of the user’s space. </param> 273 /// <param name="password"> The user’s secret word. </param> 274 /// <returns> An array of structs that contains one struct for each category. Each category struct will contain a description field that contains the name of the category. </returns> 275 /// TODO:得到博客分类 276 [XmlRpcMethod("metaWeblog.getCategories")] 277 public Category[] getCategories( 278 string blogid, 279 string username, 280 string password) 281 { 282 283 return (Category[])this.Invoke("getCategories", new object[] { blogid, username, password }); 284 } 285 } 286 #endregion 287 }
3. 编辑Form.cs,添加两个ListBox,分部命名为cats和posts,用来展示所有分类和所有随笔,同时都设置为可多选。添加3个button,分部是fresh、apply、add,以及一个文本输入框TextBox。add用来添加文本框内的分类,fresh用来删除已经有分类的随笔,apply用来应用随笔分类。
1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Linq; 7 using System.Text; 8 using System.Windows.Forms; 9 10 namespace WindowsFormsApplication1 11 { 12 public partial class Form1 : Form 13 { 14 M_MetaWeblog m_blog; 15 Post[] pp; 16 string username = ""; 17 string password = ""; 18 public Form1() 19 { 20 InitializeComponent(); 21 22 m_blog = new M_MetaWeblog(); 23 m_blog.Url = "http://www.cnblogs.com/dorothychai/services/metablogapi.aspx"; 24 25 /*Post newPost = new Post(); 26 newPost.dateCreated = DateTime.Now; 27 newPost.title = "title2"; 28 newPost.description = "description2"; 29 newPost.categories = new string[]{"[随笔分类][每周一书]生活"}; 30 newPost.mt_keywords ="keywords"; 31 string a = m_blog.newPost("_blogid", username, password, newPost, true);*/ 32 Category[] cc = m_blog.getCategories("_blogid", username, password); 33 for (int i = 0; i < cc.Length; i++) 34 { 35 cats.Items.Add(cc[i].title); 36 37 } 38 39 for (int i = 0; i < pp.Length; i++) 40 { 41 posts.Items.Add(i + ":"+pp[i].title); 42 } 43 } 44 45 private void button1_Click(object sender, EventArgs e) 46 { 47 if (cats.SelectedItems.Count == 0) 48 { 49 MessageBox.Show("请选择分类!"); 50 51 } 52 else 53 { 54 string[] cc = new string[cats.SelectedItems.Count]; 55 for (int i = 0; i < cats.SelectedItems.Count; i++) 56 { 57 cc[i] = cats.SelectedItems[i].ToString(); 58 } 59 for (int i = 0; i < posts.SelectedItems.Count; i++) 60 { 61 string ii = posts.SelectedItems[i].ToString(); 62 char[] chars = new char[1]; 63 chars[0] = ':'; 64 ii = ii.Split(chars, 2)[0]; 65 int index = System.Int32.Parse(ii); 66 67 pp[index].categories = cc; 68 m_blog.editPost(pp[index].postid, username, password, pp[index], true); 69 } 70 cats.SelectedItems.Clear(); 71 posts.SelectedItems.Clear(); 72 } 73 } 74 75 private void refresh_Click(object sender, EventArgs e) 76 { 77 posts.Items.Clear(); 78 for (int i = 0; i < pp.Length; i++) 79 { 80 if (pp[i].categories == null) 81 posts.Items.Add(i + ":" + pp[i].title); 82 } 83 } 84 85 private void add_Click(object sender, EventArgs e) 86 { 87 if (catName.Text == "") 88 catName.Text = "[随笔分类]test"; 89 if (catName.Text != null) 90 { 91 WpCategory cat = new WpCategory(); 92 cat.name = catName.Text; 93 cat.slug = "slug"; 94 cat.parent_id = 0; 95 cat.description = "desp"; 96 m_blog.newCategory("_blogid",username, password,cat); 97 } 98 cats.Items.Clear(); 99 Category[] cc = m_blog.getCategories("_blogid", username, password); 100 for (int i = 0; i < cc.Length; i++) 101 { 102 cats.Items.Add(cc[i].title); 103 104 } 105 } 106 } 107 }