一次批量修改部落格文章的經驗(上) 準備工作

2021-09-05 22:25:21 字數 3598 閱讀 6731

這幾天賦閒在家,除了看書和還債(如rss訂閱),終於把一直以來想做卻拖著的事情完成了:批量去除部落格文章段首的空格。這個過程並不難,只需要按部就班地去做就行了,一切資料都可以在網際網路上搜尋到。不過我還是打算記錄一下,也是為了今後再做類似工作時有個參考,少走一些彎路。

我是個略有些強迫症的人,希望很多東西可以統一。例如,幾個月前我才在rss訂閱裡輸出了全文——那是因為終於提供這個統一設定的選項了。其實在此之前就有很多朋友建議我開放全文,但我一直沒有做。不是我追求pv,而是我只能做到所有的新文章輸出全文,對於舊文章則必須一篇一篇地去修改——如果不修改,不就不統一了嗎?但手動修改實在太繁瑣,於是便一直沒有去做。

同樣的,在我以前的文章中,每段段首都是空兩格的,但是現在感覺沒有什麼必要,於是最近的幾十篇文章都頂格寫了。這個「不統一」我便「容忍」了,因為我知道提供了metaweblog api,這樣我理論上可以寫一段程式來批量修改之前的文章內容。只可惜,直到現在我才下決心這麼做。

整個過程分幾步完成,在此一一記錄一下。

metaweblog是乙個通用的部落格內容修改介面,許多部落格都實現了協議,因此我們可以使用windows live writer這樣的工具來寫文章。網上關於這個協議最好的描述文件我認為是msdn上的metaweblog api reference——這其實是windows live space服務所公開的介面。從理論上來說,也應該實現完全相同的功能,但是實際使用上來看,還是有一些區別。由於任務的性質,這裡我們自然以為準,我也不再去追究到底誰是真正符合標準的做法了。

metaweblog api使用了基於xml rpc的呼叫方式。xml rpc使用http來傳輸一段xml來表示乙個遠端呼叫,與soap不同,xml rpc非常簡單,他的傳輸內容您一看就懂。我只是在開發過程中使用fiddler簡單檢視了一下windows live writer與的通訊,如果您感興趣的話也可以仔細研究一下xml rpc。

在.net上呼叫xml rpc服務可以利用開源的xml-rpc.net類庫來簡化操作。雖然msdn上提供了一段基於xml-rpc.net的演示**,但是您也可以看出其實這段**無比粗略,而且我根本沒跑通,差點讓我認為xml-rpc.net非常不成熟。但我看了xml-rpc.net的文件之後才意識到,其實這個類庫使用起來非常簡單。因此,我在這裡建議您忽略msdn上的示例**,而以xml-rpc.net為準——甚至只要首頁上的幾行**您就可以明白了。

使用xml-rpc.net呼叫metaweblog api非常容易,我們只要根據api的樣式來定義「型別」和「介面」就可以了。例如:

public class 

post

public inte***ce

imetaweblogproxy : ixmlrpcproxy

首先我們定義了乙個post型別,其中有多個字段,每個欄位上標記了在xml rpc結構中的名稱。此外,我們又定義了乙個imetaweblogproxy介面型別,xml-prc.net會根據根據介面的簽名自動與遠端服務進行互動。這裡有個問題,便是post的postid欄位到底是哪個型別。msdn上描述,與windows live space的api使用的是字串,而使用的確實32位整數——如前文所述,我們這裡以為準。

呼叫介面很容易:

var client = xmlrpcproxygen.create();

client.url = "";

string username = "jeffreyzhao";

string password = "...";

string postid = "1629216";

var post = client.getpost(postid, username, password);

post.content += "hello world!

";client.updatepost(postid, username, password, post, true);

以上,便在id為1629216的文章內容後新增一行「hello world」字樣了。

f#並不是萬能的,之前我們也看到說,由於f#缺少諸多語言特性,在xml構造方面的方便程度並不如c#。但是,我這裡還是選擇使用f#,關鍵的因素還是在於其非同步支援實在是太方便了。我們的任務需要大量的網路io操作,而其中高效能的關鍵還是在於利用非同步io操作。那麼在f#中,我們又該如何非同步訪問metaweblog api呢?

其實xml-rpc.net已經為我們提供了支援,例如我們可以這樣定義上面getpost和updatepost的「非同步版本」:

type imetaweblogproxy =

inherit ixmlrpcproxy

["metaweblog.getpost")>]

abstract begingetpost : string -> string -> string -> asynccallback -> obj -> iasyncresult

["metaweblog.getpost")>]

abstract endgetpost : iasyncresult -> post

["metaweblog.editpost")>]

abstract beginupdatepost : string -> string -> string -> post -> bool -> asynccallback -> obj -> iasyncresult

["metaweblog.editpost")>]

abstract endupdatepost : iasyncresult -> bool

完整的**(如post型別的定義)您可以從文末的鏈結裡獲得。這裡我們直接定義了begin/end兩個方法的簽名,與c#版本相比省略了引數名,如果您希望保證可讀性也可以在定義時補上。只要我們使用這種方法定義了介面,標記了方法,xml-rpc.net便可以為我們生成乙個**物件。自然,我們也可以在f#中使用xmlrpcproxygen.create方法:

let createproxy() = xmlrpcproxygen.create()
在實際使用的時候,我們可以按常規來擴充套件一下imetaweblogproxy介面:

type metaweblog.imetaweblogproxy with

member p.getpostasync(postid, username, password) =

let beginget (ac, o) = p.begingetpost postid username password ac o

async.frombeginend(beginget, p.endgetpost)

member p.updatepostasync(postid, username, password, post, publish) =

let beginupdate (ac, o) = p.beginupdatepost postid username password post publish ac o

async.frombeginend(beginupdate, p.endupdatepost)

於是之前的c#**便可以改寫成如下的f#非同步工作流:

let workflow = async
當然,以上**只是進行了「定義」,在實際執行時您還需要使用某種方法來執行這個非同步工作流。

本文**

一次批量修改部落格文章的經驗(下):操作過程

一次批量修改部落格文章的經驗(下) 操作過程

metaweblog api並不提供獲取所有文章id的介面,但這並不影響我們從網頁上直接進行抓取。我們從提供的 月份彙總 頁面入手,即這樣的一張頁面。的月份彙總的url非常有規律,獲得它的html內容之後即可使用正規表示式來捕獲文章id了。您可能會想,一篇文章可能會取別名 這樣url上就不顯示id了...

一次批量操作的優化

最近在做賬務系統的批量核銷介面的優化,該介面的功能抽象來說就是暴露給另乙個系統,每次呼叫會進行計算並更新庫里的值 感覺好普通的樣子 假設我這邊的系統是r received 對方系統是s send 那麼現在的工作流程是這樣的 1.請求分充值請求和消費請求。充值請求是商戶維度的,而消費是訂單維度的。而商...

第一次爬蟲的經驗

事先宣告哈,這不是什麼教程 博主也不會 只是記錄我自己的學習經歷中的點點滴滴,如果對讀者有一丁點的作用,我也會感覺很開心。博主目前剛上大學,軟工專業的,對專案開發那是十分神往,然後進了大學就加入了乙個專案組,正準備大施拳腳,專案導師的第乙個任務就讓我傻眼了 做乙個爬蟲。要知道那時博主連python的...