利用MetaWeblog API进行Blog的批量处理

考虑到隐私问题,决定把部落格(Windows Live Space)中一些敏感的文(在特定的Category中)批量删除。这篇文就叙述一下如何利用MetaWeblog APIF#来进行这样的操作。

 

Windows Live SpaceAPI是标准的MetaWeblog API,支持getPost, newPost, deletePost这样的基本操作,这些操作一般都需要PostID。所以只要拿到我们想要删除的文章的PostID就可以批量处理了。

但问题在这个API里面没有类似getAllPosts的接口,相类似的只有getRecentPosts,而且最多只能拿到最近20个。因此光从API中我们无法知道所有文章的PostID。在这里卡了一会。但是观察最近20个文章的PostID可以发现,它符合这样的模式:

 

5E76F306F39CCB3A!5038

5E76F306F39CCB3A!5027

5E76F306F39CCB3A!4936

…………

 

前面都是相同的字符串,变化的只是后面的数字而已。这样就提供了一种思路,我们手动观察部落格里最小的ID和最大的ID是多少,由此生成类似的候选PostID,然后一个个用getPost去尝试这是不是合法的PostID。下面就好办了。

 

所以算法基本就是:

生成候选ID

|> 过滤为合法ID

|> 过滤为指定CategoryID

|> 删除!

 

利用F#的异步操作可以并行处理大量的I/O请求。这里采用了MSDN提供的MetaWeblogAPI实现,和xml-rpc.NET(因为MetaWeblog API是基于xml-rpc协议的)。同样道理还可以实现批量搬家,示例代码如下。可惜似乎由于Windows Live Space服务器并发连接数限制,I/O加速效果并不太明显(加速比约为2倍)。


 

open System;
open System.Net;
open System.IO;
open MetaWeblogApi;

let mutable mw = new MsnSpacesMetaWeblog();
let username = "YourOldUserName";
let password = "YourOldSecretWord";
mw.Credentials
<- new NetworkCredential(username, password);

let mutable mw2 = new MsnSpacesMetaWeblog();
let username2 = "YourNewUserName";
let password2 = "YourNewSecretWord"
mw2.Credentials
<- new NetworkCredential(username2, password2);

let VerifyPostId id =
async{
try
let postId = "5E76F306F39CCB3A! or your own prefix" + id.ToString();
let post = mw.getPost(postId, username, password);
printf
"%s\t" post.postid;
printfn
"%s" post.title;
return post.postid;
with
| _ -> return "";
}

let FilterPost id =
async{
let post = mw.getPost(id, username, password);
if (not(post.title = "") && post.categories |> Array.exists(fun x -> x = "Your categary")) then
printf
"%s\t" id;
printfn
"%s" post.title;
return id;
else
return
"";
}

let CopyPost id =
async{
let mutable post = mw.getPost(id, username, password);
post.dateCreated
<- DateTime.Now; //or the server will return error that illegal publish date.
mw2.newPost("MyBlog", username2, password2, post, true) |> ignore;
printf
"%s\t" post.postid;
printfn
"%s" post.title;
}

let DeletePost id =
async{
let post = mw.getPost(id, username, password);
mw.deletePost(
"MyBlog", id, username, password, true) |> ignore;
printfn
"%s" id;
}

printfn
"Skim post ids...";
let ids =
[
114..5366] //that depends on the Id range of your blog
|> List.map(fun x -> VerifyPostId x)
|> Async.Parallel
|> Async.RunSynchronously
|> Array.filter(fun x -> not(x = ""));
File.WriteAllLines(
"PostIds.txt", ids);

printfn
"Filter posts...";
let postIdsToCopy =
File.ReadAllLines(
"PostIds.txt")
|> Array.map (fun x -> FilterPost x)
|> Async.Parallel
|> Async.RunSynchronously;
File.WriteAllLines(
"PostIdsToCopy.txt", postIdsToCopy);

printfn
"Copy posts...";
File.ReadAllLines(
"PostIdsToCopy.txt")
|> Array.map (fun x -> CopyPost x)
|> Async.Parallel
|> Async.RunSynchronously
|> ignore;

printfn
"Deleting old posts..."
File.ReadAllLines(
"PostIdsToCopy.txt")
|> Array.map (fun x -> DeletePost x)
|> Async.Parallel
|> Async.RunSynchronously
|> ignore;

 

 

 

posted on 2010-07-13 00:07  grapeot  阅读(677)  评论(0编辑  收藏  举报

导航