• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            隨筆-145  評(píng)論-173  文章-70  trackbacks-0
            最近準(zhǔn)備把博客整體遷移到GitHub上面,但是由于本博客的內(nèi)容較多,因此想找個(gè)辦法進(jìn)行遷移,無(wú)奈雖然C++博客提供了備份的功能,但是保存的XML文件不是標(biāo)準(zhǔn)的Wordpress的XML格式,因此還是得自己進(jìn)行手動(dòng)遷移,無(wú)奈過(guò)去記錄的水文較多,棄之可惜,因此就想著如何進(jìn)行博客遷移,如何抓取博客內(nèi)容等一系列的問(wèn)題。

            正好,在網(wǎng)上搜索的時(shí)候,發(fā)現(xiàn)CSDN等網(wǎng)站提供MetaWeblog的標(biāo)準(zhǔn)接口用于第三方程序的接入,書寫博客,發(fā)布,刪除等一系列操作,而C++正好提供了相關(guān)接口,只需要登錄到你的賬戶,在選項(xiàng)--配置中,選擇允許Web Service以及MetaWeblog,并訪問(wèn)下面提供的MetaWeblog接口即可。

            為此,好好研讀了一下C++博客提供的接口,基本功能都已經(jīng)提供了API接口說(shuō)明,如writePost,getPost等等,對(duì)于其中用到的結(jié)構(gòu)體,如Post等,也定義了相關(guān)的成員變量的組成,類型等等,因此,實(shí)際上是比較好做的。為此,我就開始動(dòng)手,編寫自己的博客遷移工具了。

            首先確定使用的平臺(tái)和技術(shù),經(jīng)過(guò)研究,決定使用Apache XML-RPC庫(kù),并使用Java實(shí)現(xiàn)。
            其次,編寫對(duì)應(yīng)的函數(shù)和功能,初期開發(fā)講究前期驗(yàn)證,為此先凌亂的寫了幾個(gè)基本函數(shù),寫死一些變量和定義,以及所需要的Key,然后利用自己博客的一篇文章進(jìn)行驗(yàn)證,證明能夠獲取到對(duì)應(yīng)的信息,最后才保存到HTML文件中,打開后發(fā)現(xiàn)所需要的基本內(nèi)容都完好保存,因此可以進(jìn)行后續(xù)工作。
            后續(xù),主要進(jìn)行擴(kuò)展功能的展開,包括對(duì)其他接口的使用,如獲取近期所有博客,獲取分類信息,獲取博客信息等等,另外,經(jīng)過(guò)重構(gòu)后,將相關(guān)的工具函數(shù)都轉(zhuǎn)移到一個(gè)類中實(shí)現(xiàn),并盡量做到代碼復(fù)用,這個(gè)過(guò)程經(jīng)歷了幾次,漸漸發(fā)現(xiàn)最初的代碼慘不忍睹,而重構(gòu)之后,將不變的如標(biāo)記字段,服務(wù)商提供地址等等,都固定在某個(gè)類中,一旦需要應(yīng)用到其他平臺(tái),如CSDN博客,只需要做最小的修改即可,方便代碼復(fù)用。
            最后,進(jìn)行了簡(jiǎn)單測(cè)試,并發(fā)布到Github中進(jìn)行版本管理和備份,填寫相關(guān)log,后續(xù)可能會(huì)繼續(xù)做二次開發(fā)。

            上面只是簡(jiǎn)單介紹使用的技術(shù)和開發(fā)流程,至于具體的細(xì)節(jié)實(shí)現(xiàn),下面就幾個(gè)重點(diǎn)來(lái)講解:
            1. 如何發(fā)起網(wǎng)絡(luò)連接,并從服務(wù)器那邊獲取到所需要的博客信息?
            利用Apache的XML-RPC庫(kù)實(shí)現(xiàn),非常簡(jiǎn)單,只需要進(jìn)行簡(jiǎn)單配置即可,代碼如下:
            config =  new XmlRpcClientConfigImpl();
            client = new XmlRpcClient();
            config.setServerURL(new URL(url));
            client.setConfig(config); 
            這樣,就完成了客戶端的初始化和配置工作,此后,就可以直接利用此客戶端來(lái)發(fā)現(xiàn)連接請(qǐng)求,獲取對(duì)應(yīng)的信息了。
            List params = new ArrayList();
            params.add("test");
            params.add(USER_NAME);
            params.add(USER_PASSWORD);
            // 必須使用Object數(shù)組,List或者其他數(shù)組不行
            Object[] arr = (Object[])client.execute(GET_BLOGS_METHOD, params);
            發(fā)起一次請(qǐng)求時(shí),只需要先配置好參數(shù),根據(jù)每一個(gè)API文檔定義的函數(shù)參數(shù),放入到一個(gè)數(shù)組中,然后執(zhí)行對(duì)應(yīng)的函數(shù),函數(shù)名使用GET_BLOGS_METHOD之類的保存下來(lái),即可獲得對(duì)應(yīng)的結(jié)果。

            2. 如何處理獲得的結(jié)果?
            由于類型都是由API文檔中定義的,比如一篇博文的信息定義為一個(gè)Post對(duì)象,而這個(gè)對(duì)象是它定義的類,包含有標(biāo)題,時(shí)間等成員,成員的類型還可能不同,比如大部分是String類型,但是也有如Date時(shí)間這樣的類型。如何獲取呢?
            對(duì)于一個(gè)Post對(duì)象,獲得其實(shí)就是一個(gè)個(gè)鍵值對(duì),比如Key為“title”,value為對(duì)應(yīng)的值“我的博客文章”等等,因此,可以使用Java中的Map來(lái)保存一個(gè)個(gè)鍵值對(duì),但是這里我們會(huì)遇到一個(gè)疑問(wèn),Post對(duì)象既然是按照一個(gè)個(gè)鍵值對(duì)來(lái)保存,如
            {
             "title", "我的博客標(biāo)題"
             "description", "我的博客正文"
             "date", "博客發(fā)布時(shí)間"
            }
            那么,可否就直接用Map<String, String>來(lái)保存每一個(gè)鍵值,然后根據(jù)鍵來(lái)分別讀取信息呢?答案是否定的,因此并非所有的類型都是統(tǒng)一的,Key當(dāng)然都是String類型,因?yàn)槲臋n中已經(jīng)定義好了,但是Value卻可能不同,如Date對(duì)應(yīng)的值是一個(gè)Date類型,而title對(duì)應(yīng)的值是String類型,而他們都是隸屬于Post對(duì)象的,如何來(lái)處理呢?
            這里,我使用的是Map<String, Object>來(lái)存放每一個(gè)鍵值對(duì),然后根據(jù)類型獲取信息,代碼如下:
                    String title = getPostTitle(result);
                    if (title != null){
                        System.out.println(title);
                        saveString += title + "<br/>"; // 文章標(biāo)題,并以HTML形式存放
                    }

                    Date date = getPostDate(result);
                    if (date != null) {
                        String dateString = getPostTime(date);
                        System.out.println(dateString);
                        saveString += dateString + "<br/>";
                    }

                    String article = getPostArticle(result);
                    if (article != null) {
                        System.out.println(article);
                        saveString += article + "<br/>";
                    }
            當(dāng)然,這里用到了子函數(shù)實(shí)現(xiàn),但實(shí)際的效果就是,根據(jù)API文檔中的類型,在獲得value的時(shí)候,將Object類型強(qiáng)制轉(zhuǎn)換成需要的類型,比如,key為title的時(shí)候,知道值應(yīng)該是String,因此就將值轉(zhuǎn)換成String類型。Key位datedTime的時(shí)候,值的類型應(yīng)該是Date類型,就將它轉(zhuǎn)換成Date類型。這樣,最終就可以完全讀取出所有信息了。
            而對(duì)于返回值為結(jié)構(gòu)體數(shù)組的,同樣用Object數(shù)組存放,然后讀取每一個(gè)數(shù)組成員,強(qiáng)制轉(zhuǎn)化成Map<String, Object>類型,保存一個(gè)結(jié)構(gòu)體的所有鍵值對(duì),然后根據(jù)結(jié)構(gòu)體定義來(lái)逐個(gè)讀取對(duì)應(yīng)的值,當(dāng)然,如果結(jié)構(gòu)體全部都是String類型,就可以直接使用Map<String, String>來(lái)保存并讀取了。

            基本上來(lái)說(shuō),上面應(yīng)該是這些程序中的主要難點(diǎn)了,解決之后,大部分問(wèn)題也都可以完成,至于寫博客啥的,原理都是相同的,既然所有的信息都能夠讀取,就只需要賦值相關(guān)的語(yǔ)句,執(zhí)行一個(gè)對(duì)應(yīng)的函數(shù)而已了。
            當(dāng)然,在寫代碼的過(guò)程中,發(fā)現(xiàn)重構(gòu)非常重要,雖然代碼量不大,但是從歷史上來(lái)看,變化還是非常大,后期的代碼以及比前面的耦合度要低很多,而且對(duì)于固定不變的內(nèi)容等都放在類成員中,便于繼承以及代碼復(fù)用,有興趣的朋友可以試試CSDN等博客的相關(guān)功能。

            附上最終實(shí)現(xiàn)的輸出結(jié)構(gòu):
            4765
            http://www.shnenglu.com/deercoder/
            我的編程樂(lè)園
            Category Description: ACM
            Category HTML Url: http://www.shnenglu.com/deercoder/Category/17069.aspx
            Category RSS Url: http://www.shnenglu.com/deercoder/rss.aspx?catid=17069
            Category Title: ACM
            Category ID: 17069

            Category Description: Android
            Category HTML Url: http://www.shnenglu.com/deercoder/Category/17867.aspx
            Category RSS Url: http://www.shnenglu.com/deercoder/rss.aspx?catid=17867
            Category Title: Android
            Category ID: 17867

            Category Description: C++
            Category HTML Url: http://www.shnenglu.com/deercoder/Category/13117.aspx
            Category RSS Url: http://www.shnenglu.com/deercoder/rss.aspx?catid=13117
            Category Title: C++
            Category ID: 13117

            Category Description: CTeX和LateX
            Category HTML Url: http://www.shnenglu.com/deercoder/Category/13991.aspx
            Category RSS Url: http://www.shnenglu.com/deercoder/rss.aspx?catid=13991
            Category Title: CTeX和LateX
            Category ID: 13991

            Category Description: Git
            Category HTML Url: http://www.shnenglu.com/deercoder/Category/18145.aspx
            Category RSS Url: http://www.shnenglu.com/deercoder/rss.aspx?catid=18145
            Category Title: Git
            Category ID: 18145

            博客文章等保存為HTML文件,貼出HTML源碼太大,就不帖了。

            以上,就是基于MetaWeblog的博客信息讀取和遷移工作的前期工作,也是最基本的工作,后期,主要將這些函數(shù)整合并利用,就可以實(shí)現(xiàn)所有信息的本地備份,批量寫博,批量刪除,批量導(dǎo)入等工作了。

            最后,說(shuō)說(shuō)目前本工程的實(shí)現(xiàn)功能情況:
            1. 根據(jù)一篇文章的博客ID,抓取對(duì)應(yīng)的內(nèi)容,標(biāo)題和發(fā)布時(shí)間等信息(其余信息可自行添加,采用類似 的辦法,因本人只對(duì)這寫信息感興趣) 
            2. 獲取所有的分類信息和Rss訂閱信息
            3. 獲取博客信息
            4. 獲取指定數(shù)量的近期發(fā)布文章
            5. 保存為HTML頁(yè)面
            基本上,抓取博客所提供的API函數(shù)功能都已經(jīng)實(shí)現(xiàn),接下來(lái)要做的是,利用這些函數(shù),實(shí)現(xiàn)循環(huán)的遍歷所有的博客ID,然后全部讀取出來(lái),并保存,這些工作應(yīng)該就是一些功能的組合和接口設(shè)計(jì)了。

            該工程已經(jīng)發(fā)布到Github中,地址為:
            https://github.com/deercoder/blogMover,歡迎大家拍磚,指導(dǎo)。


            posted on 2012-06-10 00:07 deercoder 閱讀(1941) 評(píng)論(0)  編輯 收藏 引用 所屬分類: Java
            国内精品久久久久久野外| 97久久综合精品久久久综合| 久久电影网一区| 久久精品亚洲中文字幕无码麻豆| 久久天天躁狠狠躁夜夜躁2014| 色天使久久综合网天天| 欧美午夜A∨大片久久 | 无码人妻久久一区二区三区| 人人狠狠综合88综合久久| 国产精品永久久久久久久久久| 超级碰久久免费公开视频| 99久久免费国产精品| 亚洲国产成人久久精品影视| 久久精品国产99国产电影网| 一本久久久久久久| 国产亚洲美女精品久久久| 国产精品免费久久久久电影网| 久久久久无码国产精品不卡| 亚洲精品国产自在久久| 久久人人爽人人爽人人爽| 色88久久久久高潮综合影院| 韩国免费A级毛片久久| 国产精品久久国产精麻豆99网站| 国产精品热久久毛片| 久久精品国产99久久久香蕉| 久久只有这里有精品4| 伊人久久大香线蕉综合Av| 久久精品国产精品亚洲毛片| 国产精品岛国久久久久| 精品久久人人做人人爽综合 | A级毛片无码久久精品免费| 亚洲精品乱码久久久久久中文字幕| 久久久噜噜噜www成人网| 久久精品国内一区二区三区| 人妻丰满?V无码久久不卡| 国产69精品久久久久9999APGF | 国产精品欧美久久久天天影视| 国产69精品久久久久9999| 久久91精品国产91| 国产精品久久永久免费| 色欲综合久久躁天天躁|